pvdocs /Python/Generators

Generators

A generator is a special iterator created with a function that uses yield. It produces values lazily, one at a time.

Generator Function

def count_up(start, stop):
    while start < stop:
        yield start       # pause, return value, save state
        start += 1

gen = count_up(1, 4)
next(gen)  # 1
next(gen)  # 2
next(gen)  # 3
next(gen)  # StopIteration

# or iterate with a for loop
for n in count_up(1, 4):
    print(n)

Generator Expression

# Like a list comprehension but lazy
gen   = (x**2 for x in range(10))
total = sum(x**2 for x in range(1_000_000))  # no list in memory

Infinite Generators

def integers_from(n):
    while True:
        yield n
        n += 1

import itertools
first_10 = list(itertools.islice(integers_from(0), 10))

yield from

Delegates to a sub-generator (flattening, chaining).

def chain(*iterables):
    for it in iterables:
        yield from it

list(chain([1, 2], [3, 4], [5]))  # [1, 2, 3, 4, 5]

Two-Way Communication: send()

def accumulator():
    total = 0
    while True:
        value = yield total   # yield current total, receive next value
        total += value

acc = accumulator()
next(acc)      # prime the generator → 0
acc.send(10)   # → 10
acc.send(5)    # → 15
acc.send(3)    # → 18

Generator Pipeline (Memory-Efficient ETL)

def read_lines(path):
    with open(path) as f:
        yield from f

def filter_empty(lines):
    return (line for line in lines if line.strip())

def parse(lines):
    return (line.split(",") for line in lines)

# Only one line in memory at a time
for row in parse(filter_empty(read_lines("data.csv"))):
    process(row)

Key Interview Points