← Python lessons

Python Generators and yield: Lazy Iteration Explained

A Python generator is an iterator that produces values as you request them. Use yield to pause a function and give its caller a value.

Read Iterators first.

Yield a value and pause

Calling a generator function creates a generator. Its body starts when you request a value.

def steps():
    print("starting")
    yield 1
    print("resuming")
    yield 2

iterator = steps()
print("created")
print(next(iterator))
print(next(iterator))

created prints before starting. Each next() resumes execution until the next yield.

Generate values with a loop

The generator remembers local variables between requests. You can consume it with a for loop.

def countdown(start):
    while start > 0:
        yield start
        start -= 1

for number in countdown(3):
    print(number)

This prints 3, 2, then 1 without building a list of all the results.

End with return

yield pauses the function; return ends it. Reaching the end also stops the generator.

def before_zero(numbers):
    for number in numbers:
        if number == 0:
            return
        yield number

iterator = before_zero([4, 7, 0, 9])
print(list(iterator))
print(list(iterator))

The first list is [4, 7]. The second is empty because the generator is exhausted.

Note: Lazy iteration avoids storing every result at once. Calling list() on a generator stores all its remaining results.

See also: Generator expressions, Parameters and return.

Your turn

Add two indented yield lines to produce 5, then 10.

def bonuses():
    # add two lines: yield 5, then yield 10
    pass

print(list(bonuses()))

Expected output

[5, 10]

Practise this in the free Python course, where every exercise checks your code instantly.