Python:避免短路评估

时间:2012-09-05 12:29:45

标签: python logical-operators

这是在处理Django项目时遇到的问题。这是关于表单验证的。

在Django中,当您有提交的表单时,可以在相应的表单对象上调用is_valid()来触发验证并返回一个布尔值。所以,通常你在视图函数中有这样的代码:

if form.is_valid():
    # code to save the form data

is_valid()不仅可以验证表单数据,还可以向表单对象添加错误消息,然后可以向用户显示。

在一个页面上,我一起使用两个表单,并且只有在两个表单都包含有效数据时才希望保存数据。这意味着我必须在执行代码保存数据之前在两个表单上调用is_valid()。最明显的方式:

if form1.is_valid() and form2.is_valid():
    # ...
由于逻辑运算符的短路评估,

将无法工作。如果form1无效,则不会评估form2,并且将丢失其错误消息。

这只是一个例子。据我所知,与其他语言(即Smalltalk)一样,and / or没有贪婪的替代方案。我可以想象在不同情况下(而不仅仅是在Python中)发生的问题。我能想到的解决方案都是笨拙的(嵌套ifs,将返回值赋给局部变量并在if语句中使用它们)。我想知道解决这类问题的pythonic方法。

提前致谢!

3 个答案:

答案 0 :(得分:29)

如下:

if all([form1.is_valid(), form2.is_valid()]):
   ...

在一般情况下,可以使用列表推导,因此预先计算结果(与此上下文中常用的生成器表达式相反)。 e.g:

if all([ form.is_valid() for form in (form1,form2) ])  

这也可以很好地扩展到任意数量的条件......唯一的问题是它们都需要通过“and”连接而不是if foo and bar or baz: ...

(对于非短路or,您可以使用any代替all。)

答案 1 :(得分:15)

您可以简单地使用二进制&运算符,它将在bools上执行非短路逻辑 AND

if form1.is_valid() & form2.is_valid():
   ...

答案 2 :(得分:0)

您可以使用Clever infix hack定义自己的布尔运算符
aand = Infix(lambda x,y:bool(x)和bool(y))
1 | aand | 2将返回True而不是1