有时我会把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()

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

其他回答

请原谅我的无知,但我对#Python的了解不如在座的任何人,但我碰巧在3D BIM建模中编写自己的对象脚本时发现了类似的东西,因此我将调整我的算法以适应Python。

我在这里发现的问题是双面的:

我的价值观对于试图破译剧本的人来说似乎很陌生。如果这些值被更改(最有可能),或者如果必须添加新条件(破坏模式),代码维护将付出高昂的代价

要绕过所有这些问题,脚本必须这样运行

param_Val01 = Value 01   #give a meaningful name for param_Val(i) preferable an integer
param_Val02 = Value 02
param_Val03 = Value 03
param_Val04 = Value 04   # and ... etc

conditions = 0           # this is a value placeholder

########
Add script that if true will make:

conditions = conditions + param_Val01   #value of placeholder is updated
########

### repeat as needed


if conditions = param_Val01 + param_Val02 + param_Val03 + param_Val04:
    do something

这种方法的优点:

脚本可读。脚本很容易维护。条件是对表示期望条件的值的和的1比较操作。无需多级条件

希望它能帮助你们

我认为@zkanda的解决方案稍加改动会很好。如果您在各自的列表中列出了条件和值,则可以使用列表理解来进行比较,这将使添加条件/值对的情况更加普遍。

conditions = [1, 2, 3, 4]
values = [1, 2, 3, 4]
if all([c==v for c, v in zip(conditions, values)]):
    # do something

如果我真的想对这样的语句进行硬编码,为了易读,我会这样写:

if (condition1==value1) and (condition2==value2) and \
   (condition3==value3) and (condition4==value4):

只需要用iand运算符抛出另一个解决方案:

proceed = True
for c, v in zip(conditions, values):
    proceed &= c==v

if proceed:
    # do something

您不需要在第二个条件行上使用4个空格。可能使用:

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

此外,不要忘记空格比您想象的更灵活:

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

不过这两个都相当难看。

也许会失去括号(尽管《风格指南》不鼓励这样做)?

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

这至少给了你一些区别。

甚至:

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

我想我更喜欢:

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

这是《风格指南》,(自2010年以来)建议使用括号。

这没有多大改善,但。。。

allCondsAreOK = (cond1 == 'val1' and cond2 == 'val2' and
                 cond3 == 'val3' and cond4 == 'val4')

if allCondsAreOK:
   do_something

就我个人而言,我喜欢给长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()

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