有时我会把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
但这不是很漂亮
你能推荐另一种方法吗?
为了完整起见,只需要一些其他随意的想法。如果它们对你有用,就使用它们。否则,你最好尝试其他方法。
你也可以用字典这样做:
>>> 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语句增加意义。我必须在代码中搜索以找到合适的示例,但这是我想到的第一个示例:假设我碰巧遇到了一些奇怪的逻辑,我想根据许多变量显示某个页面。
英语:“如果登录的用户不是管理员教师,而是普通教师,而不是学生本人……”
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()
尝试在不使用变量来存储和标记逻辑的情况下编写上述条件,不仅结果是一个非常混乱、难以理解的逻辑语句,而且你自己也在重复。虽然有合理的例外,但请记住:不要重复自己(干)。
我认为@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
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 (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
}