Logical operators in Python are lazy. With the following definition:
def func(s):
print(s)
return True
calling the or
operator
>>> func('s') or func('t')
's'
only evaluates the first function call, because or
recognizes that the expression evaluates to
True
, irregardless of the return value of the second function call. and
does behave analogously.
However, when using any()
(analogously: all()
) in the following way:
>>> any([func('s'), func('t')])
's'
't'
all function calls are evaluated, because the inner list is constructed first, before any
starts to iterate over the boolean values of its items. The same happens when we omit the list construction and just write
>>> any(func('s'), func('t'))
's'
't'
That way we lose the power of any
being short-circuit, which means that it breaks as soon as the first element of the iterable is truish. If the function calls are expensive, evaluating all the functions up front is a big loss and is a waste of this ability of any
. In some sense, one could call this a Python gotcha, because it might be unexpected for users trying to leverage this feature of any
, and because any
is often thought as being just another syntactic way of chaining a sequence of or
statements. But any
is just short-circuit, not lazy, and that is a difference here.
any
is accepting an iterable. So, there should be a way of creating an iterator which does not evaluate its elements up front but pass them unevaluated to any
and lets them evaluate inside of any
only, in order to achieve a fully lazy evaluation.
So, the question is: How can we use any
with truly lazy function evaluation? That means: How can we make an iterator of function calls which any
can consume, without evaluating all the function calls in advance?