🎓 A1Learner
🔍

Python Generators

A generator is an iterator that a function builds with yield.

A list builds every value first

This function builds the full list before it returns.

def squares_list(limit):
    result = []
    for number in range(1, limit + 1):
        result.append(number * number)
    return result

print(squares_list(5))

yield hands out a value

The word yield replaces return here. The call list() collects every yielded value.

def three_numbers():
    yield 1
    yield 2
    yield 3

numbers = three_numbers()
print(list(numbers))

The body starts late

Creating the generator prints nothing from inside. The first next() starts the body.

def greetings():
    print("Starting")
    yield "Hello"
    yield "Bye"

gen = greetings()
print("Created")
print(next(gen))

State survives the pause

The variable current keeps its value between yields. Each next() resumes where the function paused.

def count_up(limit):
    current = 1
    while current <= limit:
        yield current
        current += 1

steps = count_up(3)
print(next(steps))
print(next(steps))

A sequence with no end

This generator never runs out of even numbers. You stay safe by taking only what you need.

def even_numbers():
    number = 0
    while True:
        yield number
        number += 2

evens = even_numbers()
print(next(evens))
print(next(evens))
print(next(evens))

Example

def squares_list(limit):
    result = []
    for number in range(1, limit + 1):
        result.append(number * number)
    return result

def squares_upto(limit):
    for number in range(1, limit + 1):
        yield number * number

print("List squares:", squares_list(5))
print("Generator squares:", list(squares_upto(5)))
print("Sum from list:", sum(squares_list(5)))
print("Sum from generator:", sum(squares_upto(5)))

Key points

  • Generator: an iterator that a function builds for you with yield
  • Generator function: a function whose body contains yield
  • Lazy: values are made one at a time, only when asked for
  • Use yield to hand out a value and pause the function
  • Use a generator when a sequence is long or has no end

In this example, squares_list builds all five squares before it returns. The list holds every value at once in memory. The squares_upto function uses yield instead of return. Each value is made only when the caller asks for it. The list() call collects one fresh generator into a list for printing. The sum() calls then total a second list and a second fresh generator. Both routes give the same values and the same total.

Note

Calling a generator function runs none of its body.

The body starts on the first next() and pauses at each yield.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Python Playground

Exercise

What does yield do inside a function?