Python:避免短路评估

Python:避免短路评估,python,logical-operators,Python,Logical Operators,这是我在Django项目中遇到的一个问题。这是关于表单验证的 在Django中,当您有一个提交的表单时,您可以对相应的表单对象调用is\u valid(),以触发验证并返回一个布尔值。因此,通常在视图函数中有这样的代码: 如果form.is_有效(): #保存表单数据的代码 is\u valid()不仅验证表单数据,还向表单对象添加错误消息,之后可以向用户显示这些消息 在一个页面上,我同时使用两个表单,并且仅当两个表单都包含有效数据时,才希望保存数据。这意味着在执行代码保存数据之前,我必须在两

这是我在Django项目中遇到的一个问题。这是关于表单验证的

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

如果form.is_有效():
#保存表单数据的代码
is\u valid()
不仅验证表单数据,还向表单对象添加错误消息,之后可以向用户显示这些消息

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

如果form1.is\u valid()和form2.is\u valid():
# ...
由于逻辑运算符的短路评估,无法工作。如果form1无效,则不会对form2求值,其错误消息将丢失


这只是一个例子。据我所知,在其他语言(如Smalltalk)中,除了
/
之外,没有贪婪的选择。我可以想象这个问题会在不同的情况下发生(不仅仅是在Python中)。我能想到的解决方案都有点笨拙(嵌套的ifs,将返回值赋给局部变量,并在if语句中使用它们)。我想知道解决这类问题的python方法。

比如:

if all([form1.is_valid(), form2.is_valid()]):
   ...
在一般情况下,可以使用列表理解,以便提前计算结果(与此上下文中常用的生成器表达式相反)。e、 g:

这将很好地扩展到任意数量的条件以及。。。唯一的问题是它们都需要通过“
”连接,而不是
如果foo和bar或baz:…


(对于非短路
,您可以使用
任何
而不是
所有
)。

您只需使用二进制
&
运算符,它将执行非短路逻辑AND on布尔运算

if form1.is_valid() & form2.is_valid():
   ...
您可以使用定义自己的布尔运算符
aand=中缀(λx,y:bool(x)和bool(y))

1 | a和| 2将返回True,而不是1

正是我所寻找的。非常感谢。我花了几秒钟才想出这个。这是一个我以前从未考虑过的极端情况(我经常使用Fortran,它不保证短路,但允许短路),我总是试图找出如何确保我的表达式短路。对我来说,搞清楚这一点有点倒退:)。是的,
all
是一种方法,但是你在哪里使用了列表理解?在你的例子中我只看到一个简单的列表。@rantanplan--你说得对。(哎呀)。我想在一般情况下,可以使用列表理解。我会解决这个问题。还要注意,上面的表单可以与@BigYellowCactus提供的解决方案结合使用,因为
any
all
返回布尔值。更具体地说,它将对整数执行位
运算。因为bool恰好是从
True==1
False==0
的整数中派生出来的,所以这是可行的。它(不一定)适用于其他类型或返回非布尔值的函数。尽管如此,它仍然是一个很好的工具,可以使(+1)比mgilson的解决方案更简单。谢谢你!另一个可能对阅读代码的其他人更有帮助。在这里,我想你可能会认为我把
&
@mgilson混淆了
all
函数也是我想到的第一个解决方案(我会使用它的原因正是j0ker提到的),但我发现这个问题的答案太晚了(+1,顺便说一句):-)与我的解决方案相比的一个优点是,如果所有结果都是布尔值(
True
False
1
0
),那么您就不仅仅局限于
)。您可以编写一个表达式,如
if foo()&baz()| bar()
,它的行为应该与预期的一样。与这里的一些其他注释相反,这个答案是完全正确的。事实上,这是专门设计和预期的布尔行为
bool
甚至有自己的
bool.\uuu和uu
返回
True
,而不是
1
,对于
True&True
,以及类似的其他位运算符,因此它不仅继承int实现(尽管它与int行为兼容)。
if form1.is_valid() & form2.is_valid():
   ...