🌊Generators: yield, yield from, send()LESSON

Generators: yield, yield from, send()

Generators are one of Python's most elegant features. They let you write iterators with ordinary function syntax, produce values lazily (on demand), and compose powerful data pipelines — all while using dramatically less memory than building full lists.

Generator Functions and yield

A generator function looks like a regular function but uses yield instead of return. When called, it doesn't execute immediately — it returns a generator object (which is an iterator):

Execution is suspended at each yield. The function's local state (variables, position in the code) is preserved between calls to next().

Generator Objects Are Iterators

Generator objects implement both __iter__ and __next__, so they work everywhere iterators work:

Lazy Evaluation — Values on Demand

The key advantage: a generator only computes the next value when you ask for it. This is called lazy evaluation:

Memory Comparison: list vs generator

For large sequences, generators use O(1) memory while lists use O(n):

Generator Expressions

Just as list comprehensions have a concise syntax, generators do too — use parentheses instead of brackets:

Generator State: Lifecycle

A generator moves through distinct states:

yield from — Delegating to Sub-generators

yield from iterable delegates to another iterable, yielding all its values:

yield from also properly handles send() and throw() calls by forwarding them to the sub-generator.

send() — Passing Values Into a Generator

Generators are not just one-way pipes. You can send values back in with gen.send(value). The yield expression receives the sent value:

Important: You must call next(gen) (or gen.send(None)) first to advance to the first yield before you can send() a non-None value.

Practical Uses

Infinite sequences without memory cost:

Data pipelines — chain transformations lazily:

Knowledge Check

What does a generator function return when called?

When is the body of a generator function first executed?

What is the purpose of `yield from subgenerator`?