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?