Sobes.tech
Junior — Senior

Features of filter and one-time iterators

livecode

Task condition

Analyze why this program outputs exactly this result and what features of filter and iterators lead to this.

seq = [1, 2, 3, 4, 5]

# Get an iterator of odd numbers from seq
odd_iter = filter(lambda x: x % 2, seq)

if any(odd_iter):
    print("Has odds:")
    for odd in odd_iter:
        print(odd)

print(any(odd_iter))

Program output:

Has odds:
3
5
False

What happens:

  1. filter returns an iterator, not a list. Its elements are computed "on the fly" and can only be retrieved once.
  2. In the condition if any(odd_iter): the any function iterates over the iterator until it finds a true (True) value. The first two odd numbers — 1 and 3 — are checked, and once 3 (a true value) is found, the iteration stops. The iterator has already been "advanced" past the element 3 to 5.
  3. After executing any, the iterator is in a "spent" state: the elements that have already been passed are no longer accessible. Therefore, in the subsequent for odd in odd_iter: only the remaining element — 5 — is left, which is printed.
  4. The last call any(odd_iter) again tries to iterate over the remaining elements. Since after printing 5 there are no more elements in the iterator, any immediately returns False.

In summary, filter creates a one-time iterator, and any functions that consume it (any, list, for loop, etc.) "exhaust" it, making subsequent attempts to retrieve data empty.