stackademic

The leading education platform for anyone with an interest in software development.

Python Generators

Lazy iterators with yield for memory-efficient data processing

Overview

Generators produce values one at a time using yield, pausing between items. They are iterators without storing the full sequence in memory—ideal for large files, infinite streams, and pipeline processing.

Syntax / Usage

# Generator function
def countdown(n):
    while n > 0:
        yield n
        n -= 1

for i in countdown(3):
    print(i)  # 3, 2, 1

# Generator expression (like list comp but lazy)
squares = (x ** 2 for x in range(1_000_000))

# Send values into a generator
def echo():
    while True:
        received = yield
        print(received)

gen = echo()
next(gen)       # prime the generator
gen.send("hi")  # prints hi

# yield from delegates to sub-iterator
def chain_lists(a, b):
    yield from a
    yield from b

Examples

Read a large log file line by line without loading it all:

def read_lines(path):
    with open(path) as f:
        for line in f:
            yield line.strip()

for line in read_lines("huge.log"):
    if "ERROR" in line:
        print(line)

Pipeline: filter then transform:

def evens(numbers):
    for n in numbers:
        if n % 2 == 0:
            yield n

def double(numbers):
    for n in numbers:
        yield n * 2

result = list(double(evens(range(10))))
# [0, 4, 8, 12, 16]

Common Mistakes

  • Exhausting a generator—iterators are single-use; create a new one to replay
  • Using a generator when you need random access or len()—use a list
  • Forgetting to prime generators that use .send()
  • Confusing generator expressions () with tuples (x,) when no comprehension syntax is used

See Also

python-list-comprehension python-loops python-decorators