在“if”语句中设置多行条件的样式?[关闭]

2025-03-04 08:25:00
admin
原创
71
摘要:问题描述:有时我会将 s 中的长条件拆分if成几行。最明显的方法是: if (cond1 == 'val1' and cond2 == 'val2' and cond3 == 'val3' and cond4 == 'val4'): do_something 从视觉上看,这不是很吸引...

问题描述:

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

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

从视觉上看,这不是很吸引人,因为操作与条件混合在一起。但是,使用正确的 Python 缩进(4 个空格)是自然的方式。

目前我正在使用:

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

但这不是很漂亮。:-)

您能推荐其他方法吗?


解决方案 1:

您不需要在第二个条件行上使用 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 \n   cond3 == 'val3' and cond4 == 'val4':
    do_something

这至少给你一些区别。

甚至:

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

我认为我更喜欢:

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

这是样式指南,自 2010 年起,建议使用括号。

解决方案 2:

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

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

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

它删减了一些字符并明确表示情况没有什么微妙之处。

解决方案 3:

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

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

解决方案 4:

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

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

是的,为了清晰起见,我们牺牲了一些垂直空间。在我看来,这是值得的。

解决方案 5:

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

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

if allCondsAreOK:
   do_something

解决方案 6:

以下是我个人的看法:在我看来,长条件是一种代码异味,建议将其重构为布尔返回函数/方法。例如:

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

现在,如果我找到一种方法使多行条件看起来不错,我可能会对它们感到满意并跳过重构。

另一方面,让它们扰乱我的审美感可以成为重构的动力。

因此,我的结论是,多条线路的情况看起来很糟糕,这是一种避免它们的动机。

解决方案 7:

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

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

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

解决方案 8:

似乎值得引用PEP 0008(Python 的官方风格指南),因为它对这个问题进行了适度的详细评论:

当 -statement 的条件部分if足够长,需要将其写在多行中时,值得注意的是,两个字符关键字(即if)加上一个空格加上一个左括号的组合会为多行条件的后续行创建自然的 4 个空格缩进。这可能会与嵌套在 -statement 内的缩进代码套件产生视觉冲突if,后者也会自然缩进为 4 个空格。本 PEP 没有明确说明如何(或是否)进一步在视觉上将这些条件行与 -statement 内的嵌套代码套件区分开来if。在这种情况下,可接受的选项包括但不限于:

# No extra indentation.
if (this_is_one_thing and
    that_is_another_thing):
    do_something()

# Add a comment, which will provide some distinction in editors
# supporting syntax highlighting.
if (this_is_one_thing and
    that_is_another_thing):
    # Since both conditions are true, we can frobnicate.
    do_something()

# Add some extra indentation on the conditional continuation line.
if (this_is_one_thing
        and that_is_another_thing):
    do_something()

请注意上面引文中的“不限于”;除了样式指南中建议的方法之外,该问题的其他答案中建议的一些方法也是可以接受的。

解决方案 9:

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

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

if all(condition):
   do_something

解决方案 10:

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

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

解决方案 11:

补充一下 @krawyoti 所说的内容... 长条件很难读,也很难理解。使用函数或变量可以使代码更清晰。在 Python 中,我更喜欢使用垂直空格、用括号括起来,并将逻辑运算符放在每行的开头,这样表达式看起来就不会像“浮动”一样。

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

如果需要多次评估条件(如在while循环中),则最好使用本地函数。

解决方案 12:

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

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

最近我更喜欢allandany函数,因为我很少混合使用 And 和 Or 比较,所以它效果很好,并且还具有通过生成器理解提前失败的额外优势:

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

只需记住传入单个可迭代对象!传入 N 个参数是不对的。

注意:any就像许多比较一样orall就像许多比较一样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!")

更多内容:生成器理解

解决方案 13:

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

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

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

因为我是从你关于 C++ 的博客文章中发现这个问题的,所以我会说明我的 C++ 风格是相同的:

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

解决方案 14:

我很惊讶没有看到我喜欢的解决方案,

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

因为and是一个关键字,所以它会被我的编辑器突出显示,并且看起来与其下面的 do_something 有足够的不同。

解决方案 15:

“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

解决方案 16:

我认为 @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 \n   (condition3==value3) and (condition4==value4):

iand并且只是用操作员提出另一个解决方案:

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

if proceed:
    # do something

解决方案 17:

如果我们仅在条件和主体之间插入一个额外的空白行,并按照规范的方式完成其余操作,会怎么样?

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

    do_something

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

解决方案 18:

我通常会这样做:

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

这样,结束的括号和冒号就从视觉上标记了我们条件的结束。

解决方案 19:

我知道这个线程很旧,但是我有一些 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 能咬紧牙关,直接使用花括号。我想知道这些年来有多少错误是由于意外的错误缩进而意外引入的...

解决方案 20:

所有受访者也为 if 语句提供了多条件,这与提出的问题一样丑陋。你不能通过做同样的事情来解决这个问题。

甚至 PEP 0008 的答案也令人厌恶。

这是一个更易读的方法

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

想让我食言吗?如果你能说服我你需要多重条件,我就会把这句话打印出来,供你消遣。

解决方案 21:

为了完整性,这里只是随便举几个例子。如果它们对你有用,就用它们。否则,你最好尝试其他方法。

你也可以用字典来做到这一点:

>>> 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'

最后两个我还没有测试过,但是如果你想要的话,这些概念应该足以帮助你。

(并且根据记录,如果这只是一次性的事情,那么您最好使用您最初提出的方法。如果您在很多地方进行比较,这些方法可能会增强可读性,让您不会因为它们有点黑客而感到难过。)

解决方案 22:

我也一直在努力寻找一个合适的方法来做到这一点,所以我只是想出了一个主意(不是灵丹妙药,因为这主要是品味问题)。

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

我有点喜欢这个,因为当你看到它时,脑子里会立刻响起一个铃声:“嘿,这里有一件复杂的事情!”。是的,我知道括号对可读性没有帮助,但这些情况应该很少出现,当它们出现时,你无论如何都必须停下来仔细阅读它们(因为它们很复杂)。

无论如何,这里还有两个我没见过的提议。希望这对某些人有帮助 :)

解决方案 23:

你可以把它分成两行

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

或者甚至一次添加一个条件。这样,至少可以将混乱从中分离出来if

解决方案 24:

请原谅我的菜鸟,但事实上我对 #Python 的了解并不像你们任何人那么丰富,不过我在 3D BIM 建模中编写自己的对象脚本时发现了类似的东西,所以我会将我的算法改编为 Python 的算法。

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

  1. 对于试图解读该脚本的人来说,这些价值观似乎很陌生。

  2. 如果这些值发生变化(最有可能),或者必须添加新条件(破坏模式),则代码维护的成本将很高

为了绕过所有这些问题,你的脚本必须像这样运行

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. 脚本可读。

  2. 脚本易于维护。

  3. 条件是对表示所需条件的值的总和进行 1 比较运算。

  4. 无需多级条件

希望对大家有帮助

解决方案 25:

将您的条件打包成一个列表,然后执行以下操作:

if False not in Conditions:
    do_something

解决方案 26:

我发现,当我有较长的条件时,我通常会使用较短的代码主体。在这种情况下,我只需双缩进主体,因此:

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

解决方案 27:

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

或者如果这样更清楚:

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

在这种情况下,缩进没有必要是 4 的倍数,例如参见“与打开分隔符对齐”:

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

解决方案 28:

这是另一种方法:

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

解决方案 29:

我通常使用:

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

解决方案 30:

如果我们的 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
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2757  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1693  
  在全球化的浪潮下,企业的业务范围不断拓展,跨文化协作变得愈发普遍。不同文化背景的团队成员在合作过程中,由于语言、价值观、工作习惯等方面的差异,往往会面临诸多沟通挑战。而产品生命周期管理(PLM)系统作为企业管理产品全生命周期的重要工具,如何有效支持跨文化协作成为了关键问题。通过合理运用沟通策略,PLM系统能够在跨文化团...
plm是什么软件   15  
  PLM(产品生命周期管理)系统在企业的产品研发、生产与管理过程中扮演着至关重要的角色,其中文档版本控制是确保产品数据准确性、完整性和可追溯性的关键环节。有效的文档版本控制能够避免因版本混乱导致的错误、重复工作以及沟通不畅等问题,提升企业整体的运营效率和产品质量。接下来,我们将深入探讨 PLM 系统实现文档版本控制的 6...
plm是什么意思   19  
  PLM(产品生命周期管理)项目管理旨在通过有效整合流程、数据和人员,优化产品从概念到退役的整个生命周期。在这个过程中,敏捷测试成为确保产品质量、加速交付的关键环节。敏捷测试强调快速反馈、持续改进以及与开发的紧密协作,对传统的测试流程提出了新的挑战与机遇。通过对测试流程的优化,能够更好地适应PLM项目的动态变化,提升产品...
plm管理系统   18  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用