Is the Shortcircuit Behaviour of Python's Any/All Explicit

Is the shortcircuit behaviour of Python's any/all explicit?

The behaviour is guaranteed. I've contributed a patch, which was accepted and merged recently, so if you grab the latest sources you will see that the short-circuiting behaviour is now explicitly enforced.

git clone https://github.com/python/cpython.git
grep Short-circuit cpython/Lib/test/test_builtin.py

Does Python's `all` function use short circuit evaluation?

Yes, it short-circuits:

>>> def test():
... yield True
... print('one')
... yield False
... print('two')
... yield True
... print('three')
...
>>> all(test())
one
False

From the docs:

Return True if all elements of the iterable are true (or if the iterable is empty). Equivalent to:

def all(iterable):
for element in iterable:
if not element:
return False
return True

So when it returns False, then the function immediately breaks.

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

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.)

Does Python support short-circuiting?

Yep, both and and or operators short-circuit -- see the docs.

all vs and AND any vs or

The keywords and and or follow Python's short circuit evaluation rules. Since all and any are functions, all arguments would be evaluated. It's possible to get different behaviour if some of the conditions are functions calls.

Is any() evaluated lazily?

Yes, any() and all() short-circuit, aborting as soon as the outcome is clear: See the docs:

all(iterable)

Return True if all elements of the iterable are true (or if the
iterable is empty). Equivalent to:

def all(iterable):
for element in iterable:
if not element:
return False
return True

any(iterable)

Return True if any element of the iterable is true. If the iterable is
empty, return False. Equivalent to:

def any(iterable):
for element in iterable:
if element:
return True
return False


Related Topics



Leave a reply



Submit