Introduction
If you've been writing Python code, you will definitely find yourself writing functions to solve tasks.
For example, consider this function:
def function_1(x: int):
for i in range(11):
print(f'{x}*{i} = {x*i}')
Its behavior is straightforward — it prints a multiplication table. But what about this version?
def function_2(x: int):
for i in range(11):
yield f'{x}*{i} = {x*i}'
The keyword yield may not be obvious at first. Let's break it down.
return vs yield
function_1 with x=5 prints:
5*0 = 0
5*1 = 5
5*2 = 10
...
5*10 = 50
function_2 does not print anything immediately. Instead, yield suspends the function's execution and sends a value back to the caller — but retains enough state to resume exactly where it left off.
This means its code produces a series of values over time, rather than computing them all at once.
Generator Functions
The yield statement is only used in generator functions. When a generator function is called, it returns a generator iterator (a generator object). The body is executed lazily — only when you call next() on it:
gen = function_2(5)
print(next(gen)) # "5*0 = 0"
print(next(gen)) # "5*1 = 5"
Or iterate it:
for line in function_2(5):
print(line)
How yield Works Internally
When yield is executed:
- The current state (local variables, instruction pointer, evaluation stack) is frozen
- The yielded value is returned to
next()'s caller - On the next
next()call, execution resumes immediately after theyield
Advantages of yield
- Memory efficient — values are generated one at a time, not stored all at once
- Lazy evaluation — computation happens only when needed
- Stateful — the generator remembers its position between calls
Disadvantages
- Can be harder to debug without appropriate logging
- Cannot be reused — a consumed generator is exhausted
Practical Example
Generators shine when working with large datasets:
def read_large_file(filepath):
with open(filepath) as f:
for line in f:
yield line.strip()
# Processes lines one at a time — never loads the full file into memory
for line in read_large_file("huge_dataset.txt"):
process(line)
The associated notebook for this post is available on GitHub.