How to Use Generators in Python (yield statement)

Learn how to write generators in Python. Understand the yield keyword, lazy evaluation, memory optimization, and compare generators with list structures.

Try Code in Editor

Explanation

When working with massive datasets, log files, or infinite data streams, loading all elements into memory simultaneously (like returning a large list) can easily exhaust system RAM and crash your application. Python offers a brilliant, memory-efficient solution: Generators.

A generator is a special type of function that returns a lazy iterator. Instead of computing all values at once and returning them, a generator yields values one-by-one as requested. The key difference is the `yield` statement. When a generator function calls `yield`, it pauses its execution state (variables, instruction pointer) and returns the yielded value. When the next value is requested, the function resumes exactly where it paused.

Because generator calculations are executed lazily, they use almost zero memory regardless of the dataset size. Python also supports generator expressions, which use parenthetical syntax `(x for x in data)` to create lightweight inline generators without declaring full functions.

Step-by-Step Implementation

  1. 1

    Define a function using the standard def keyword.

  2. 2

    Use the yield keyword instead of return to yield values back to the iterator stream.

  3. 3

    Iterate over the generator using a for loop or call the built-in next(gen) function to extract values.

  4. 4

    Use generator expressions (using parentheses) for simple, inline lazy conversions.

Code Example

This script demonstrates generating sequences using generator functions with the yield statement and generator expressions.

generators_demo.py
Try in Editor
# 1. Generator function using yield
def count_up_to(limit):
    count = 1
    while count <= limit:
        yield count
        count += 1

# Instantiating the generator
counter = count_up_to(3)
print("Memory safe generator instantiated.")

# Fetching values manually
print("Next 1:", next(counter))
print("Next 2:", next(counter))
print("Next 3:", next(counter))

# 2. Iterating with a for loop (automatically handles StopIteration)
print("\n--- Looping over generator ---")
for num in count_up_to(4):
    print("Num:", num)

# 3. Generator expression (Shorthand syntax)
squares_gen = (x**2 for x in range(1, 4))
print("\nGenerator expression elements:")
print(list(squares_gen)) # Cast to list to print all elements
Terminal Output
Memory safe generator instantiated.
Next 1: 1
Next 2: 2
Next 3: 3

--- Looping over generator ---
Num: 1
Num: 2
Num: 3
Num: 4

Generator expression elements:
[1, 4, 9]

Frequently Asked Questions

What is the main advantage of generators over lists?

Memory efficiency. Lists store all elements in RAM simultaneously, while generators yield items one-by-one on demand, allowing you to process datasets that are larger than your system's total memory.

What happens when a generator runs out of items?

Python raises a StopIteration exception. A for loop catches this exception automatically to exit the loop gracefully, but calling next() on an exhausted generator manually will throw the exception.

Related How-To Guides

Recommended Python Resources

Expand your knowledge with related interactive tutorials, cheat sheets, and code comparisons.