嵌套的 if 语句、简洁的代码和 Pythonic,带有控制器/键盘输入

Posted

技术标签:

【中文标题】嵌套的 if 语句、简洁的代码和 Pythonic,带有控制器/键盘输入【英文标题】:Nested if-statements, clean code, and being Pythonic, with controller/keyboard input 【发布时间】:2014-04-10 00:49:33 【问题描述】:

首先是背景:我使用 Python 和 PyGame。我已经尝试过编写自己的输入/控制器模块,它允许用户以他们喜欢的任何方式重新映射控件。这必然要求编写我的代码来处理不同类型的输入(例如,键盘键、控制器按钮和控制器轴/帽子/等)

例如,如果“右”按钮映射到箭头键,则处理 GetPush("Right")GetRelease("Right") 的代码将与映射到沿某个轴按下的控制杆有所不同。为了帮助解决这个问题,我创建了一个辅助函数__GetButtonType(),它——正如名称所回答的——返回它是什么类型的按钮。对于此处显示的代码,按钮被称为字符串。字符串的第一个字母表示按钮类型,其余表示按钮。例如k97 指的是值为97 的键盘键。 (A键。)

现在讨论手头的问题。我的代码做我想做的事。但是当我开始清理它时,我遇到了一个困扰我的部分。我有以下处理来自键盘的按键的代码段。 (DoSomething() 函数替换了完全不相关的代码,我认为这与手头的问题无关。)

for n in TheController.ControlMap:
    if __GetButtonType(n)=="key":
        if event.type == KEYUP:
            if event.key == int(n[1:]): DoSomething()
        if event.type == KEYDOWN:
            if event.key == int(n[1:]): DoSomethingElse()

这件事在我看来有点不对劲。可能是重复了if event.key == int(n[1:]) 条件。这似乎很浪费。但是,如果event.key 不是KEYUPKEYDOWN,那么该事件将没有关键属性(这就是pyGame 的工作方式,这不是我的设计。)这意味着条件if (event.type == KEYDOWN and event.key == int(n[1:]) 将只要event.type 是别的东西,就会抛出一个错误。

不过,我想了想,发现我可以通过以下方式将代码缩短一行:

for n in TheController.ControlMap:
    if event.type == KEYUP:
        if __GetButtonType(n)=="key" and event.key == int(n[1:]): DoSomething()
    if event.type == KEYDOWN:
        if __GetButtonType(n)=="key" and event.key == int(n[1:]): DoSomethingElse()

两种代码 sn-ps 都有效。两者都做同样的事情。第一个看起来更容易阅读,但不是很多。第二个使用较少的行。我的问题是这样的:

哪种风格“更好”?一个执行速度是否比另一个执行快不可忽略的数量?或者只是被认为是“糟糕的做法”?也许他们俩都是,事实上。我对编程还是比较陌生。

谢谢,

克里斯

【问题讨论】:

这肯定会使这部分代码看起来更干净。毫无疑问。但是,如果我没有误解某些东西,那不就是将解析问题重新定位到其他地方吗? DoSomething 函数仍然必须使用嵌套的 if 语句来确定如何处理参数,不是吗? 【参考方案1】:

你的两个陈述都有一个相同的特点,会让人畏缩。等效的if 语句重复两次。这不好,因为它会干扰您的代码并且绝对没有必要:

if event.type in [KEYUP, KEYDOWN] and __GetButtonType(n)=="key" and event.key == int(n[1:]):
    if event.type == KEYUP:
        DoSomething()
    elif event.type == KEYDOWN:
        DoSomethingElse()

这里的第一个条件确保您不会在event.key 上收到错误。

也使用elif,因为这些选项是互斥的。简单的else 也足够了,但为了便于阅读,我会留下elif。您也可以将其隐藏到DoSomething(event.type)


另一个可能看起来难看或漂亮取决于你问谁的选项是将它全部折叠成一个扁平的 if-else:

if event.type in [KEYUP, KEYDOWN] and __GetButtonType(n)=="key" and event.key == int(n[1:]):
    (DoSomething if event.type == KEYUP else DoSomethingElse)()

但这有点奇怪......不过,它仍然有效。


在性能方面,这里绝对没有什么可担心的。优化是另一回事,首先要优化的是程序设计/算法,而不是局部低重要性命令。

【讨论】:

非常丰富的答案。非常感激。这不仅回答了这个问题,它还以我未来的代码有望变得更好的方式来解释它。谢谢。【参考方案2】:

根据“sashkello”提到的内容,我的 pygame 程序中通常有以下代码块。

   for event in pygame.event.get():

        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT :
               do_something()
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT:
               do_something_else()

【讨论】:

以上是关于嵌套的 if 语句、简洁的代码和 Pythonic,带有控制器/键盘输入的主要内容,如果未能解决你的问题,请参考以下文章

一名Android程序员如何减少代码中该死的-if-else-嵌套,怎么让代码更简洁?

arttemplate if else 能不能嵌套

在嵌套使用if语句时,C语言规定else总是和之前与其最近的if配对?

Switch case 语句怎么使用

最小化包含并以表达式为条件的if语句[重复]

Python基础之控制结构