Lesson 35 / 47

Generators & yield

Functions that produce values lazily, one at a time, saving memory.

A generator function

yield pauses a function and hands back a value; the function resumes right there on the next call — no need to build the whole list in memory.

def count_up_to(n):
    i = 1
    while i <= n:
        yield i
        i += 1

for num in count_up_to(5):
    print(num)          # 1 2 3 4 5, one at a time

Generator expressions

A generator expression looks like a list comprehension with () instead of [], and produces values lazily too.

squares = (n * n for n in range(1_000_000))  # nothing computed yet
print(next(squares))   # 0
print(next(squares))   # 1
print(sum(n * n for n in range(10)))   # 285

Quick check: Why prefer a generator over a list for a huge sequence?

  • It runs faster in every case
  • It produces items lazily instead of storing them all in memory
  • It automatically sorts the items
Answer

It produces items lazily instead of storing them all in memory — Generators compute one value at a time on demand, so huge or infinite sequences don't need to fit in memory.