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

但这不是很漂亮

你能推荐另一种方法吗?


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

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

if allCondsAreOK:
   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年以来)建议使用括号。


我建议将和关键字移到第二行,并用两个空格而不是四个空格缩进包含条件的所有行:

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

这正是我在代码中解决这个问题的方法。将关键字作为行中的第一个单词可以使条件更加可读,并且减少空格的数量可以进一步区分条件和操作。


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

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

在退化情况下,我采用了以下方法,即简单的AND或or。

if all( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

if any( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):

它剃掉了几个字符,并清楚地表明没有任何微妙的条件。


“all”和“any”适用于同一类型case的许多条件。但他们总是评估所有条件。如本例所示:

def c1():
    print " Executed c1"
    return False
def c2():
    print " Executed c2"
    return False


print "simple and (aborts early!)"
if c1() and c2():
    pass

print

print "all (executes all :( )"
if all((c1(),c2())):
    pass

print

这里必须有人支持使用垂直空格!:)

if (     cond1 == val1
     and cond2 == val2
     and cond3 == val3
   ):
    do_stuff()

这使每个条件都清晰可见。它还允许更清晰地表达更复杂的条件:

if (    cond1 == val1
     or 
        (     cond2_1 == val2_1
          and cond2_2 >= val2_2
          and cond2_3 != bad2_3
        )
   ):
    do_more_stuff()

是的,为了清晰起见,我们在交易一些垂直房地产。非常值得。


为了完整起见,只需要一些其他随意的想法。如果它们对你有用,就使用它们。否则,你最好尝试其他方法。

你也可以用字典这样做:

>>> x = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> y = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> x == y
True

此选项比较复杂,但您可能也会发现它很有用:

class Klass(object):
    def __init__(self, some_vars):
        #initialize conditions here
    def __nonzero__(self):
        return (self.cond1 == 'val1' and self.cond2 == 'val2' and
                self.cond3 == 'val3' and self.cond4 == 'val4')

foo = Klass()
if foo:
    print "foo is true!"
else:
    print "foo is false!"

不知道这是否对你有用,但这是另一种选择。还有一种方法:

class Klass(object):
    def __init__(self):
        #initialize conditions here
    def __eq__(self):
        return (self.cond1 == 'val1' and self.cond2 == 'val2' and
               self.cond3 == 'val3' and self.cond4 == 'val4')

x = Klass(some_values)
y = Klass(some_other_values)
if x == y:
    print 'x == y'
else:
    print 'x!=y'

最后两个我还没有测试过,但如果你想使用这些概念,那么这些概念应该足以让你继续下去。

(顺便说一句,如果这只是一次性的事情,你可能会更好地使用你最初提出的方法。如果你在很多地方进行比较,这些方法可能会增强可读性,让你不会因为它们有点粗糙而感到很糟糕。)


如果我们只在条件和主体之间插入一个额外的空白行,然后以规范的方式执行其余的操作,会怎么样?

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

    do_something

p.s.我总是使用制表符,而不是空格;我无法微调。。。


将您的条件打包到列表中,然后执行smth。如:

if False not in Conditions:
    do_something

(我对标识符进行了轻微修改,因为固定宽度的名称不能代表真实代码——至少不能代表我遇到的真实代码——并且会掩盖示例的可读性。)

if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4"):
    do_something

这适用于“和”和“或”(重要的是它们位于第二行的第一位),但对于其他较长的条件就更不适用了。幸运的是,前者似乎是更常见的情况,而后者往往很容易用临时变量重写。(这通常不难,但在重写时保持“和”/“或”的短路可能很难或不那么明显/可读。)

由于我在你的关于C++的博客文章中发现了这个问题,我将补充我的C++风格是相同的:

if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4") {
    do_something
}

这是我个人的看法:长条件(在我看来)是一种代码气味,建议重构为布尔返回函数/方法。例如:

def is_action__required(...):
    return (cond1 == 'val1' and cond2 == 'val2'
            and cond3 == 'val3' and cond4 == 'val4')

现在,如果我找到了一种让多行条件看起来很好的方法,我可能会发现自己满足于拥有它们,并跳过重构。

另一方面,让它们扰乱了我的审美意识,这是一种重构的激励。

因此,我的结论是,多行条件应该看起来很难看,这是避免它们的一种激励。


我很惊讶没有看到我的首选解决方案,

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

因为和是一个关键字,所以它会被我的编辑器高亮显示,并且看起来与下面的do_something完全不同。


加上@krawyoti所说的。。。长时间的环境气味难闻,因为它们难以阅读和理解。使用函数或变量可以使代码更清晰。在Python中,我更喜欢使用垂直空格,括起括号,并将逻辑运算符放在每一行的开头,这样表达式看起来不像“浮动”。

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

如果需要对条件进行多次求值,例如在while循环中,那么最好使用局部函数。


我发现当我有长条件时,我通常有一个短代码体。在这种情况下,我只需将主体缩进两次,这样:

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

在这种情况下,缩进不应该是4的倍数,例如,请参见“与开头分隔符对齐”:

http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Indentation#Indentation


就我个人而言,我喜欢给长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 (cond1 == 'val1' and cond2 == 'val2' and
    cond3 == 'val3' and cond4 == 'val4'
   ):
    do_something

这样,右括号和冒号可视地标志着我们的状态结束。


下面是另一种方法:

cond_list = ['cond1 == "val1"','cond2=="val2"','cond3=="val3"','cond4=="val4"']
if all([eval(i) for i in cond_list]):
 do something

这也使得只需将另一个条件附加到列表中,就可以轻松地添加另一条件,而无需更改if语句:

cond_list.append('cond5=="val5"')

这是我要做的,记住“all”和“any”接受一个可迭代的,所以我只是在列表中放置一个长条件,让“all”完成工作。

condition = [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4']

if all(condition):
   do_something

简单明了,也通过了pep8检查:

if (
    cond1 and
    cond2
):
    print("Hello World!")

近年来,我一直倾向于使用所有和任何函数,因为我很少将“与”和“或”进行比较,这很有效,并且具有“早期失败”和生成器理解的额外优势:

if all([
    cond1,
    cond2,
]):
    print("Hello World!")

只需记住传入一个可迭代的!传入N个参数不正确。

注意:任何一个都像许多或比较,所有都像许多和比较。


这很好地结合了生成器的理解,例如:

# Check if every string in a list contains a substring:
my_list = [
    'a substring is like a string', 
    'another substring'
]

if all('substring' in item for item in my_list):
   print("Hello World!")

# or

if all(
    'substring' in item
    for item in my_list
):
    print("Hello World!")

更多内容:生成器理解


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

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()

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

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


我通常使用:

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-anelse条件必须在其中执行多个语句,那么我们可以像下面这样写。每当我们有if-else示例时,其中都有一个语句。

谢谢为我工作。

#!/usr/bin/python
import sys
numberOfArgument =len(sys.argv)
weblogic_username =''
weblogic_password = ''
weblogic_admin_server_host =''
weblogic_admin_server_port =''


if numberOfArgument == 5:
        weblogic_username = sys.argv[1]
        weblogic_password = sys.argv[2]
        weblogic_admin_server_host =sys.argv[3]
        weblogic_admin_server_port=sys.argv[4]
elif numberOfArgument <5:
        print " weblogic UserName, weblogic Password and weblogic host details are Mandatory like, defalutUser, passwordForDefaultUser, t3s://server.domainname:7001 ."
        weblogic_username = raw_input("Enter Weblogic user Name")
        weblogic_password = raw_input('Enter Weblogic user Password')
        weblogic_admin_server_host = raw_input('Enter Weblogic admin host ')
        weblogic_admin_server_port = raw_input('Enter Weblogic admin port')
#enfelif
#endIf

你可以把它分成两行

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

甚至一次添加一个条件。这样,至少可以将杂乱与if分开。


我知道这个线程很旧,但我有一些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语句提供多条件的回答者都和问题一样难看。你不能通过做同样的事情来解决这个问题。。

即使是PEP 0008的答案也令人反感。

这里有一种更易读的方法

condition = random.randint(0, 100) # to demonstrate
anti_conditions = [42, 67, 12]
if condition not in anti_conditions:
    pass

要我收回我的话吗?让我相信你需要多个条件句,我会把它打印出来,然后吃给你消遣。


我认为@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

请原谅我的无知,但我对#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比较操作。无需多级条件

希望它能帮助你们