This is a problem that occurred to me while working on a Django project. It's about form validation.
In Django, when you have a submitted form, you can call is_valid()
on the corresponding form object to trigger the validation and return a Boolean value. So, usually you have code like that inside your view functions:
if form.is_valid(): # code to save the form data
is_valid()
not only validates the form data but also adds error messages to the form object that can afterwards be displayed to the user.
On one page I use two forms together and also want the data to be saved only if both forms contain valid data. That means I have to call is_valid()
on both forms before executing the code to save the data. The most obvious way:
if form1.is_valid() and form2.is_valid(): # ...
won't work because of the short circuit evaluation of logical operators. If form1
is not valid, form2
will not be evaluated and its error messages would be missing.
That's only an example. As far as I know, there is no greedy alternative to and
/or
as in other languages (i.e. Smalltalk). I can imagine that problem occurring under different circumstances (and not only in Python). The solutions I could think of are all kind of clumsy (nested if
s, assigning the return values to local variables and using them in the if
statement). I would like to know the pythonic way to solve this kind of problem.
Short-Circuit Evaluation: Short-circuiting is a programming concept in which the compiler skips the execution or evaluation of some sub-expressions in a logical expression. The compiler stops evaluating the further sub-expressions as soon as the value of the expression is determined.
The logical AND operator performs short-circuit evaluation: if the left-hand operand is false, the right-hand expression is not evaluated. The logical OR operator also performs short-circuit evaluation: if the left-hand operand is true, the right-hand expression is not evaluated.
Short-circuit evaluation The logical AND expression is a short-circuit operator. As each operand is converted to a boolean, if the result of one conversion is found to be false , the AND operator stops and returns the original value of that falsy operand; it does not evaluate any of the remaining operands.
Short-circuiting the evaluation of an expression means that only a part of the expression needs to be evaluated before finding its value. For example: a == null || a.size() == 0. If a is null , the a.
How about something like:
if all([form1.is_valid(), form2.is_valid()]): ...
In a general case, a list-comprehension could be used so the results are calculated up front (as opposed to a generator expression which is commonly used in this context). e.g.:
if all([ form.is_valid() for form in (form1,form2) ])
This will scale up nicely to an arbitrary number of conditions as well ... The only catch is that they all need to be connected by "and
" as opposed to if foo and bar or baz: ...
.
(for a non-short circuiting or
, you could use any
instead of all
).
You can simply use the binary &
operator, which will do a non-short-circuit logical AND on bools.
if form1.is_valid() & form2.is_valid(): ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With