提问人:Eli Bendersky 提问时间:10/8/2008 最后编辑:General GrievanceEli Bendersky 更新时间:5/16/2023 访问量:1593648
在“if”语句中设置多行条件的样式?[已结束]
Styling multi-line conditions in 'if' statements? [closed]
问:
有时我会将 s 中的长条件分解为几行。最明显的方法是: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 年以来)建议使用括号。
评论
我建议将关键字移动到第二行,并用两个空格而不是四个空格缩进所有包含条件的行:and
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
For decades the recommended style was to break after binary operators. But this can hurt readability in two ways
In Python code, it is permissible to break before or after a binary operator, as long as the convention is consistent locally. For new code Knuth's style is suggested.
在退化的情况下,我采用了以下方法,它只是 AND 或 OR。
if all( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):
if any( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):
它剃掉了几个字符,并清楚地表明这种情况没有微妙之处。
评论
if destroy_world and DestroyTheWorld() == world_is_destroyed: ...
“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
评论
all()
f()
必须有人在这里支持使用垂直空白!:)
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。
评论
and
or
PEP8
and
or
为了完整起见,只是其他一些随机的想法。如果它们对您有用,请使用它们。否则,你最好尝试别的东西。
您也可以使用字典来执行此操作:
>>> 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
这适用于“and”和“or”(重要的是它们在第二行的第一行),但对于其他长条件则不那么有效。幸运的是,前者似乎是更常见的情况,而后者通常很容易用临时变量重写。(这通常并不难,但在重写时保留“and”/“or”的短路可能很困难或不太明显/可读。
由于我从您关于 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完全不同。and
评论
补充@krawyoti说的......长时间的条件闻起来是因为它们难以阅读和理解。使用函数或变量可使代码更清晰。在 Python 中,我更喜欢使用垂直空格,用括号括起来,并将逻辑运算符放在每行的开头,这样表达式就不会看起来像“浮动”。
conditions_met = (
cond1 == 'val1'
and cond2 == 'val2'
and cond3 == 'val3'
and cond4 == 'val4'
)
if conditions_met:
do_something
如果需要多次评估条件,例如在循环中,则最好使用局部函数。while
评论
Path(input).is_dir()
Path(input).is_file()
TypeError: 'bool' object is not callable
我发现,当我有长条件时,我经常有一个短代码正文。在这种情况下,我只是对正文进行双缩进,因此:
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 语句需要做很多工作。我们把逻辑分配给有意义的标签怎么样。“label”实际上是变量名称:
displayTeacherPanel = not user.isAdmin() and user.isTeacher() and not user.isStudent()
if displayTeacherPanel:
showTeacherPanel()
这可能看起来很傻,但您可能还有另一种情况,即您只想显示另一个项目,当且仅当您显示教师面板或用户默认有权访问该其他特定面板时:
if displayTeacherPanel or user.canSeeSpecialPanel():
showSpecialPanel()
尝试在不使用变量来存储和标记逻辑的情况下编写上述条件,不仅最终会得到一个非常混乱、难以阅读的逻辑语句,而且您也只是重复了自己。虽然有合理的例外,但请记住:不要重复自己 (DRY)。
我通常做的是:
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
评论
cond4
cond2
cond1
object is not None and object.param == 5 and object.is_running()
condition = cond1 == 'val1' and cond2 == 'val2' ...
简单明了,也通过了 pep8 检查:
if (
cond1 and
cond2
):
print("Hello World!")
最近,我一直更喜欢 and 函数,因为我很少混合 And 和 Or 比较,这效果很好,并且具有与生成器理解一起提前失败的额外优势:all
any
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!")
More on: generator comprehension
评论
I've been struggling to find a decent way to do this as well, so I just came up with an idea (not a silver bullet, since this is mainly a matter of taste).
if bool(condition1 and
condition2 and
...
conditionN):
foo()
bar()
I find a few merits in this solution compared to others I've seen, namely, you get exactly an extra 4 spaces of indentation (bool), allowing all conditions to line up vertically, and the body of the if statement can be indented in a clear(ish) way. This also keeps the benefits of short-circuit evaluation of boolean operators, but of course adds the overhead of a function call that basically does nothing. You could argue (validly) that any function returning its argument could be used here instead of bool, but like I said, it's just an idea and it's ultimately a matter of taste.
Funny enough, as I was writing this and thinking about the "problem", I came up with yet another idea, which removes the overhead of a function call. Why not indicate that we're about to enter a complex condition by using extra pairs of parentheses? Say, 2 more, to give a nice 2 space indent of the sub-conditions relative to the body of the if statement. Example:
if (((foo and
bar and
frob and
ninja_bear))):
do_stuff()
I kind of like this because when you look at it, a bell immediatelly rings in your head saying "hey, there's a complex thing going on here!". Yes, I know that parentheses don'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).
Anyway, just two more proposals that I haven't seen here. Hope this helps someone :)
I usually use:
if ((cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4')):
do_something()
似乎值得引用 PEP 0008(Python 的官方风格指南),因为它对这个问题的评论不多:
当 -statement 的条件部分足够长,需要跨多行编写时,值得注意的是,两个字符关键字的组合(即 ),加上一个空格,加上一个左括号,为多行条件的后续行创建一个自然的 4 空格缩进。这可能会与嵌套在 -语句中的缩进代码套件产生视觉冲突,该代码套件自然也会缩进到 4 个空格。对于如何(或是否)进一步直观地将此类条件行与 -语句中的嵌套套件区分开来,此 PEP 没有明确的立场。在这种情况下,可接受的选项包括但不限于:
if
if
if
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()
请注意上面引文中的“不限于”;除了风格指南中建议的方法外,这个问题的其他答案中建议的一些方法也是可以接受的。
评论
如果我们的 if & an 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
你可以把它分成两行
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 I did want to hard-code a statement like this, I would write it like this for legibility:
if (condition1==value1) and (condition2==value2) and \
(condition3==value3) and (condition4==value4):
And just to throw another solution out there with an iand
operator:
proceed = True
for c, v in zip(conditions, values):
proceed &= c==v
if proceed:
# do something
评论
all(map(eq, have, expected))
from operator import eq
)
Pardon my noobness, but it happens that I'm not as knowledgeable of #Python as anyone of you here, but it happens that I have found something similar when scripting my own objects in a 3D BIM modeling, so I will adapt my algorithm to that of python.
The problem that I find here, is double sided:
- Values my seem foreign for someone who may try to decipher the script.
- Code maintenance will come at a high cost, if those values are changed (most probable), or if new conditions must be added (broken schema)
Do to bypass all these problems, your script must go like this
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
Pros of this method:
Script is readable.
Script can be easy maintained.
- conditions is a 1 comparison operation to a sum of values that represents the desired conditions.
- No need for multilevel conditions
Hope it help you all
评论
pep8
pep8