如何防止评估短路?

问题描述

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

在Django中,当您有一个提交的表单时,您可以在相应的Form对象上调用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中)。我能想到的解决方案都有些笨拙(嵌套的if,将返回值赋给局部变量并在if语句中使用它们)。我想知道解决这类问题的方法。


解决方案

不如这样:

if all([form1.is_valid(), form2.is_valid()]):
   ...
在一般情况下,可以使用列表理解,以便预先计算结果(而不是在此上下文中通常使用的生成器表达式)。例如:

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

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

(对于非短路or,可以使用any而不是all)。

相关文章