Generators & yield
Generators exist in both languages — but Python leans on them harder
Section titled “Generators exist in both languages — but Python leans on them harder”TypeScript has generators too: function* with yield works almost identically at first glance. You get a lazy iterator, you can call .next(), and the function suspends between yields. But in Python, generators are not a niche feature — they are woven into the standard library. range(), file iteration, zip(), map(), filter(), and the entire itertools module all return lazy iterators built on the same generator protocol. Even async/await in Python is built on top of generators internally. If you understand Python generators, you understand a large slice of the language.
Defining and consuming a generator
Section titled “Defining and consuming a generator”A Python generator is any function that contains a yield statement. Calling it returns a generator object — no code runs until you iterate.
// TypeScript generator with function*function* countUp(start: number, stop: number): Generator<number> { let current = start; while (current <= stop) { yield current; current++; }}
const gen = countUp(1, 5);for (const val of gen) { process.stdout.write(val + " ");}console.log();
// Infinite generatorfunction* fibonacci(): Generator<number> { let [a, b] = [0, 1]; while (true) { yield a; [a, b] = [b, a + b]; }}
const fib = fibonacci();const firstTen = Array.from({ length: 10 }, () => fib.next().value);console.log(firstTen);# Python generator with def + yielddef count_up(start, stop): current = start while current <= stop: yield current current += 1
gen = count_up(1, 5)for val in gen: print(val, end=" ")print()
# Infinite generatordef fibonacci(): a, b = 0, 1 while True: yield a a, b = b, a + b
fib = fibonacci()first_ten = [next(fib) for _ in range(10)]print(first_ten)Key differences to notice:
- Python uses a plain
def— there is nofunction*syntax. The presence ofyieldanywhere in the function body makes it a generator automatically. - Python’s
forloop works directly with any iterable, including generators, without needing to call.next()manually. - TypeScript requires annotating the return type as
Generator<T>; Python infers it automatically.
Two-way communication with send()
Section titled “Two-way communication with send()”Python generators support two-way data flow. You can send a value back into a paused generator using .send(). The sent value becomes the result of the yield expression inside the generator. TypeScript generators support this via gen.next(value), but the feature is less commonly used in the TS ecosystem.
// TypeScript: sending values into a generatorfunction* accumulator(): Generator<number, void, number> { let total = 0; while (true) { const value = yield total; if (value === undefined) break; total += value; }}
const acc = accumulator();acc.next(); // prime the generatorconsole.log(acc.next(10).value); // 10console.log(acc.next(20).value); // 30console.log(acc.next(5).value); // 35# Python: sending values into a generator with .send()def accumulator(): total = 0 while True: value = yield total if value is None: break total += value
acc = accumulator()next(acc) # prime the generator (advance to first yield)print(acc.send(10)) # 10print(acc.send(20)) # 30print(acc.send(5)) # 35Try it
Section titled “Try it”def count_up(start, stop): current = start while current <= stop: yield current current += 1
gen = count_up(1, 5)for val in gen: print(val, end=" ")print()
def fibonacci(): a, b = 0, 1 while True: yield a a, b = b, a + b
fib = fibonacci()first_ten = [next(fib) for _ in range(10)]print(first_ten)Loading Python runtime (first run only)…