Any/All python short-circuit: Why doesn't the following work?

Viewed 179
2 Answers

Your code errors because the expressions have to be evaluated before being passed into the function.

In this context, short-circuiting actually means that as soon as they find a different value, they return and don't bother checking the remaining values. It's not the same kind of short-circuiting that and and or do, which can actually avoid evaluating expressions.

To illustrate, let's use an iterator, which will get consumed:

>>> a = iter([1, 0, 2, 3])
>>> all(a)  # Search until a falsy value
False
>>> list(a)  # Show what's left in the iterator
[2, 3]

You can see that it consumed 1 and 0, returning on 0 because it's falsy.


Now, if you did want to do lazy evaluation with any and all, you could call lambdas in a generator expression:

>>> any(e() for e in [lambda: 1, lambda: 0, lambda: 2/0])
True
>>> all(e() for e in [lambda: 1, lambda: 0, lambda: 2/0])
False

(Thanks to this question for inspiring this bit.)

Yes, short circuting happens in python

In [23]: False and 3/0
Out[23]: False

In [24]: True and 3/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-24-a08823d6496a> in <module>
----> 1 True and 3/0

ZeroDivisionError: division by zero

Using the dis module,

In [32]: dis.dis("all([True, 2+2, False, 2/0])")
  1           0 LOAD_NAME                0 (all)
              2 LOAD_CONST               0 (True)
              4 LOAD_CONST               1 (4)
              6 LOAD_CONST               2 (False)
              8 LOAD_CONST               3 (2)
             10 LOAD_CONST               4 (0)
             12 BINARY_TRUE_DIVIDE
             14 BUILD_LIST               4
             16 CALL_FUNCTION            1
             18 RETURN_VALUE

In [33]: dis.dis("any(True, 2+2, False, 2/0)")
  1           0 LOAD_NAME                0 (any)
              2 LOAD_CONST               0 (True)
              4 LOAD_CONST               1 (4)
              6 LOAD_CONST               2 (False)
              8 LOAD_CONST               3 (2)
             10 LOAD_CONST               4 (0)
             12 BINARY_TRUE_DIVIDE
             14 CALL_FUNCTION            4
             16 RETURN_VALUE

When you look at the function calls, BINARY_TRUE_DIVIDE is evaluated before any or all because expressions get evaluated first before any function call

Related