首页 文章

在'if'语句中设置多行条件的样式?

提问于
浏览
506

有时我会在 if s中将长条件分成几行 . 最明显的方法是:

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

但这不是很漂亮 . :-)

你能推荐另一种方式吗?

30 回答

  • 1

    这是另一种方法:

    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"')
    
  • 3

    为了完整性,还有一些其他随机的想法 . 如果它们适合您,请使用它们 . 否则,你可能最好不要尝试别的东西 .

    您也可以使用字典执行此操作:

    >>> 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!"
    

    Dunno,如果这适合你,但它是另一个考虑的选择 . 这是另一种方式:

    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'
    

    最后两个我还没有测试过,但是这些概念应该足以让你继续前进,如果那是你想要的 .

    (并且为了记录,如果这只是一次性事情,你可能最好使用你最初提出的方法 . 如果你在很多地方进行比较,这些方法可以提高可读性,足以使对于他们有点hacky这一事实,你并不觉得这么糟糕 . )

  • 102

    我认为@ 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 operator抛出另一个解决方案:

    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
    

    由于 and 是一个关键字,它会被我的编辑器突出显示,并且看起来与它下面的do_something完全不同 .

  • 16

    我通常使用:

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

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

    当if语句的条件部分足够长以要求它跨多行写入时,值得注意的是两个字符关键字(即if),加上单个空格和一个左括号的组合会创建一个多行条件的后续行的自然4空格缩进 . 这可能与嵌套在if -statement中的缩进代码集产生视觉冲突,该代码集自然也会缩进到4个空格 . 该PEP没有明确地说明如何(或是否)进一步在视觉上将这些条件线与if-statement内的嵌套套件区分开来 . 在这种情况下可接受的选项包括但不限于:#无额外缩进 .
    if(this_is_one_thing和
    that_is_another_thing):
    做一点事()

    #添加注释,这将在编辑器中提供一些区别
    #支持语法高亮显示 .
    if(this_is_one_thing和
    that_is_another_thing):
    #由于这两个条件都属实,我们可以讨厌 .
    做一点事()

    #在条件连续行上添加一些额外的缩进 .
    if(this_is_one_thing
    和that_is_another_thing):
    做一点事()

    注意上面引用中的“不限于”;除了风格指南中提出的方法之外,在这个问题的其他答案中提出的一些方法也是可以接受的 .

  • 3

    你可以把它分成两行

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

    或者甚至一次添加一个条件 . 这样,至少它将杂乱与 if 分开 .

  • 0
    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

  • 0

    这并没有太大改善,但......

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

    “all”和“any”对于相同类型情况的许多条件都很好 . 但他们总是评估所有条件 . 如下例所示:

    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
    
  • 10

    简单,也通过pep8检查:

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

    最近我一直更喜欢 allany 函数,因为我很少混合And和Or比较这很有效,并且具有早期失败与生成器理解的额外优势:

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

    只记得传递一个可迭代的!传入N参数是不正确的 .

    注意: any 就像许多 or 比较, all 就像许多 and 比较 .


    这与发电机理解很好地结合,例如:

    # 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!")
    

    更多信息:generator comprehension

  • 19

    我一直在努力找到一个合适的方法来做到这一点,所以我想出了一个想法(不是一个银弹,因为这主要是品味问题) .

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

    我在这个解决方案中找到了一些与我见过的其他优点相比,即你得到了额外的4个缩进空间(bool),允许所有条件垂直排列,并且if语句的主体可以缩进清楚的(ish)办法 . 这也保留了布尔运算符的短路评估的好处,但当然增加了函数调用的开销,它基本上什么都不做 . 您可以(有效地)争论任何返回其参数的函数都可以在这里使用而不是bool,但就像我说的那样,这只是一个想法,它最终是一个品味问题 .

    有趣的是,当我写这篇文章并思考"problem"时,我提出了另一个想法,它消除了函数调用的开销 . 为什么不通过使用额外的括号表示我们即将进入复杂条件?再说2,给出相对于if语句主体的子条件的2个空格缩进 . 例:

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

    我有点像这样,因为当你看着它的时候,你的脑袋里响起了一声铃声,说着"hey, there's a complex thing going on here!" . 是的,我知道括号不是't help readability, but these conditions should appear rarely enough, and when they do show up, you are going to have to stop and read them carefuly anyway (because they' re complex ) .

    无论如何,我还没有看到另外两个提案 . 希望这有助于某人:)

  • 20

    将你的条件打包成一个列表,然后做smth . 喜欢:

    if False not in Conditions:
        do_something
    
  • 2

    我知道这个线程很老,但是我有一些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能够咬紧牙关并且只是花了大括号 . 我想知道多年来由于意外误压而意外引入了多少漏洞......

  • 1

    我在退化的情况下使用了以下内容,它只是简单的AND或OR .

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

    它削减了一些角色,并清楚地表明这种情况并没有微妙之处 .

  • 1

    如果我们的if和else条件必须在其中执行多个语句,那么我们可以像下面那样编写 . 每当我们有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
    
  • 0

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

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

    您不需要在第二个条件行上使用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
    

    但这两个都相当难看 .

    也许会失去括号(Style Guide虽然不鼓励这个)?

    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
    

    这是Style Guide,(自2010年起)建议使用括号 .

  • 551

    (我已经轻微地修改了标识符,因为固定宽度的名称不代表真实的代码 - 至少不是我遇到的真实代码 - 并且会相信一个例子的可读性 . )

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

    这适用于“和”和“或”(重要的是它们首先在第二行),但对于其他长期条件则更少 . 幸运的是,前者似乎是更常见的情况,而后者通常很容易用临时变量重写 . (这通常并不难,但在重写时保留“和”/“或”的短路可能很困难或不那么明显/可读 . )

    自从我从your blog post about C++发现这个问题以来,我将包含我的C风格相同:

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

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

    尝试编写上述条件而不使用变量来存储和标记逻辑,不仅最终会得到一个非常混乱,难以阅读的逻辑语句,而且你也只是重复自己 . 虽然有合理的例外,但请记住:不要重复自己(干) .

  • 0

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

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

    现在,如果我找到一种方法使多线条件看起来很好,我可能会发现自己满足于使用它们并跳过重构 .

    另一方面,让它们扰乱我的审美意识,就会成为重构的动力 .

    因此,我的结论是,多线条件应该看起来很丑陋,这是避免它们的动机 .

  • 5

    所有为if语句提供多条件的受访者都同样丑陋因为问题出现了 . 你不做同样的事情来解决这个问题 .

    即使是PEP 0008答案也是令人厌恶的 .

    这是一种更易读的方法

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

    要我吃我的话吗?说服你,你需要多条件,我会打印出来并为了你的娱乐而吃它 .

  • 0

    我通常做的是:

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

    这样,闭合支架和结肠在视觉上标志着我们病情的结束 .

  • 1

    我猜这样的东西是最可读的选项:

    for pet in zoo:
        cute = every_pet()
        furry = hair is 'over9000'
        small = size < min_size
        if cute and furry and small:
            return 'I need to feed it!'
    
  • 3

    添加到@krawyoti所说的......长条件闻起来因为它们难以阅读且难以理解 . 使用函数或变量使代码更清晰 . 在Python中,我更喜欢使用垂直空间,括起括号,并将逻辑运算符放在每行的开头,因此表达式看起来不像“浮动” .

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

    如果需要多次评估条件,如 while 循环,那么最好使用局部函数 .

  • 3

    我发现当我有很长的条件时,我经常会有一个简短的代码体 . 在那种情况下,我只是双重缩进身体,因此:

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

    如果我们只在条件和身体之间插入一个额外的空白线并以规范的方式完成剩下的工作怎么办?

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

    附:我总是使用制表符,而不是空格;我不能微调......

  • 20

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

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

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

  • 0

    这就是我所做的,记住“所有”和“任何”都接受一个可迭代的,所以我只是在列表中放了一个长条件,让“all”完成工作 .

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

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

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

    是的,为了清晰起见,我们正在对一些垂直房地产进行折衷 . 非常值得IMO .

相关问题