Is Any() Evaluated Lazily?
Solution 1:
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: returnFalsereturnTrue
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: returnTruereturnFalse
Solution 2:
While the all()
and any()
functions short-circuit on the first "true" element of an iterable, the iterable itself may be constructed in a non-lazy way. Consider this example:
>> any(x == 100for x inrange(10**8))
True
This will take several seconds to execute in Python 2 as range(10**8)
constructs a list of 10**8 elements. The same expression runs instantly in Python 3, where range()
is lazy.
Solution 3:
As Tim correctly mentioned, any
and all
do short-circuit, but in your code, what makes it lazy is the use of generators. For example, the following code would not be lazy:
print(any([slow_operation(x) for x in big_list]))
The list would be fully constructed and calculated, and only then passed as an argument to any
.
Generators, on the other hand, are iterables that calculate each item on demand. They can be expressions, functions, or sometimes manually implemented as lazy iterators.
Solution 4:
Yes, it's lazy as demonstrated by the following:
defsome(x, result=True):
print(x)
return result
>>> print(any(some(x) for x inrange(5)))
0True>>> print(any(some(x, False) for x inrange(5)))
01234False
In the first run any()
halted after testing the first item, i.e. it short circuited the evaluation.
In the second run any()
continued testing until the sequence was exhausted.
Solution 5:
Yes, and here is an experiment that shows it even more definitively than your timing experiment:
import random
defsome(x):
print(x, end = ', ')
return random.random() < 0.25for i inrange(5):
print(any(some(x) for x inrange(10)))
typical run:
0, 1, 2, True0, 1, True0, True0, 1, 2, 3, True0, 1, 2, 3, 4, 5, 6, 7, 8, 9, False
Post a Comment for "Is Any() Evaluated Lazily?"