有时我会把if中的长条件分解成几行。最明显的方法是:

  if (cond1 == 'val1' and cond2 == 'val2' and
      cond3 == 'val3' and cond4 == 'val4'):
      do_something

视觉上不是很吸引人,因为动作与环境融为一体。然而,这是使用4个空格的正确Python缩进的自然方式。

目前我正在使用:

  if (    cond1 == 'val1' and cond2 == 'val2' and
          cond3 == 'val3' and cond4 == 'val4'):
      do_something

但这不是很漂亮

你能推荐另一种方法吗?


当前回答

似乎值得引用PEP 0008(Python的官方风格指南),因为它对这个问题的评论篇幅适中:

如果if语句的条件部分足够长,需要跨多行编写,那么值得注意的是,两个字符的关键字(即if)加上一个空格和一个左括号的组合会为多行条件语句的后续行创建一个自然的4空格缩进。这可能会与嵌套在if语句中的缩进代码集产生视觉冲突,这也会自然缩进到4个空格。对于如何(或是否)进一步从视觉上区分if语句中的嵌套套件和这些条件行,PEP没有明确的立场。这种情况下可接受的选项包括但不限于:#无额外压痕。如果(this_is_one_thing和that_is_aother_thing):do_something()#添加注释,这将在编辑器中提供一些区别#支持语法高亮显示。如果(this_is_one_thing和that_is_aother_thing):#既然这两个条件都成立,我们就可以结婚了。do_something()#在条件延续行上添加一些额外的缩进。如果(this_is_one_thing和that_is_aother_thing):do_something()

请注意上述报价中的“不限于”;除了风格指南中建议的方法外,其他问题答案中建议的一些方法也是可以接受的。

其他回答

我通常使用:

if ((cond1 == 'val1' and cond2 == 'val2' and
     cond3 == 'val3' and cond4 == 'val4')):
    do_something()

我知道这个线程很旧,但我有一些Python 2.7代码,PyCharm(4.5)仍然抱怨这个例子:

if foo is not None:
    if (cond1 == 'val1' and cond2 == 'val2' and
        cond3 == 'val3' and cond4 == 'val4'):
            # some comment about do_something
            do_something

即使有PEP8警告“视觉缩进的行与下一个逻辑行缩进相同”,实际代码也完全正常?这不是“过度缩进?”

……有时我希望Python能咬紧牙关,只带上大括号。我想知道这些年来有多少错误是由于错误的缩进而被意外引入的。。。

当我有一个非常大的if条件时,我更喜欢这种风格:

if (
    expr1
    and (expr2 or expr3)
    and hasattr(thingy1, '__eq__')
    or status=="HappyTimes"
):
    do_stuff()
else:
    do_other_stuff()

就我个人而言,我喜欢给长if语句增加意义。我必须在代码中搜索以找到合适的示例,但这是我想到的第一个示例:假设我碰巧遇到了一些奇怪的逻辑,我想根据许多变量显示某个页面。

英语:“如果登录的用户不是管理员教师,而是普通教师,而不是学生本人……”

if not user.isAdmin() and user.isTeacher() and not user.isStudent():
    doSomething()

当然,这看起来很好,但阅读那些if语句是一项艰巨的工作。我们把逻辑分配给有意义的标签怎么样。“标签”实际上是变量名:

displayTeacherPanel = not user.isAdmin() and user.isTeacher() and not user.isStudent()
if displayTeacherPanel:
    showTeacherPanel()

这可能看起来很愚蠢,但您可能还有另一种情况,即您只想显示另一个项目,如果您正在显示教师面板,或者用户默认可以访问其他特定面板:

if displayTeacherPanel or user.canSeeSpecialPanel():
    showSpecialPanel()

尝试在不使用变量来存储和标记逻辑的情况下编写上述条件,不仅结果是一个非常混乱、难以理解的逻辑语句,而且你自己也在重复。虽然有合理的例外,但请记住:不要重复自己(干)。

我也一直在努力找到一种体面的方式来做这件事,所以我只是想出了一个主意(不是银弹,因为这主要是品味问题)。

if bool(condition1 and
        condition2 and
        ...
        conditionN):
    foo()
    bar()

与我见过的其他解决方案相比,我发现这个解决方案有一些优点,即,您可以获得额外的4个缩进空间(bool),允许所有条件垂直排列,并且if语句的主体可以以清晰的方式缩进。这也保留了布尔运算符短路求值的优点,但当然增加了基本上什么都不做的函数调用的开销。您可以(有效地)辩称,任何返回其参数的函数都可以在这里使用,而不是bool,但正如我所说,这只是一个想法,最终还是一个口味问题。

有趣的是,当我写这篇文章并思考“问题”时,我想到了另一个想法,它消除了函数调用的开销。为什么不使用额外的括号对来表示我们将要进入一个复杂的条件呢?再多说2个,以相对于if语句的主体对子条件进行2个空格的缩进。例子:

if (((foo and
      bar and
      frob and
      ninja_bear))):
    do_stuff()

我有点喜欢这样,因为当你看着它时,一个铃声立刻在你的脑海中响起:“嘿,这里发生了一件复杂的事情!”。是的,我知道括号对可读性没有帮助,但这些条件应该很少出现,当它们出现时,你必须停下来仔细阅读它们(因为它们很复杂)。

总之,还有两个我没有看到的提案。希望这对某人有所帮助:)