Iterators & Generators

A track of P29 · Functions, Decorators & Generators.

Rebuild the iterator protocol, replace it with yield, and exploit laziness on endless streams; then contextlib context managers and send() open the doorway from generators to coroutines and P33's async world.

Here is a task that breaks the obvious solution: compute a sliding average over a log stream that never ends. list(stream) never returns — the input is infinite. Yet the working code is four lines with a yield in them, and it handles ten items or ten billion in the same constant memory. The difference between those two programs — materialise everything, or produce values on demand — is this track's subject.

It starts by rebuilding what every for loop does: call iter() once, then next() until StopIteration. You implement the protocol by hand (__iter__, __next__, staying exhausted once done) so it is machinery, not folklore — and then replace the whole class with a generator function, where yield suspends the frame, locals and position preserved, and resumes on the next pull. Laziness follows for free: a paginator written with yield serves its first page from an endless itertools.count() at the same cost as from a seven-item string, and small lazy tools chain into constant-memory pipelines — a sliding window over a filter over a counter, pulled one step at a time.

The closing module is the pillar's hand-off. contextlib.contextmanager turns a one-yield generator into a with block — setup above the yield, guaranteed teardown below, rollback in a try/except around it. Then the doorway: yield is an expression, gen.send(x) resumes the frame with a value, and a generator you drive that way is already a coroutine. That is the lineage async/await gave dedicated syntax to, and P33 — Asyncio & Coroutines — walks through exactly this door when it arrives.

Protocoliter, next, StopIterationyieldthe frame suspendsLazinessendless streams, constant memoryDoorwaysend() - toward coroutines
From the for-loop's machinery to the suspended frames behind async.