Python Generators

Let’s look at generators

  1. Notice

    A generator yields values lazily. yield pauses its execution, and the next request resumes it from that point.

  2. Try

    Follow the example, change its sample, and compare what happens.

  3. Check

    Explain the result and test your understanding.

Watch how it works

Focus on how the names, objects, and calculations change. We’ll inspect the printed output in the next section.

Explore the idea

Follow the code and watch its state change. Guided simulation.

Code
Python
def countdown(number):
    while number > 0:
        yield number
        number -= 1
values = countdown(3)
print(next(values, "done"))
print(next(values, "done"))
Live state

Top-level scope

countdown→Object 1
values→Object 2
Object 1 · functionfunction countdownObject 2 · generator<generator object countdown>
This step

A generator yields values lazily. yield pauses its execution, and the next request resumes it from that point.

Picture generators

A generator yields values lazily. yield pauses its execution, and the next request resumes it from that point.

Image brief

Alt text
A diagram for Python Generators. Instructions: def countdown(number): while number > 0: yield number number -= 1 values = countdown(3) print(next(values, "done")) print(next(values, "done")). Displayed result: 3 2. The final example bindings are countdown --> object 1 (function); values --> object 2 (generator). object 1: function countdown; object 2: <generator object countdown>
Image generation prompt
Create a clean educational illustration for a Python programming lesson titled "Python Generators". Teaching focus: A generator yields values lazily. yield pauses its execution, and the next request resumes it from that point. Depict exactly the relationships and labels in this reference diagram: EXAMPLE INSTRUCTIONS def countdown(number): while number > 0: yield number number -= 1 values = countdown(3) print(next(values, "done")) print(next(values, "done")) | v DISPLAYED RESULT 3 2 FINAL BINDINGS countdown --> object 1 (function) values --> object 2 (generator) object 1: function countdown object 2: <generator object countdown> Use a flat vector style, generous spacing, clear arrows and legible labels, with a restrained blue/teal palette on a plain background. The diagram must explain the programming idea accurately. Do not depict variables as boxes containing copied objects when they share a reference. Avoid mascots, decorative screenshots, logos, gradients and extra text. Landscape composition, approximately 3:2, suitable for a course card. Accessible description: A diagram for Python Generators. Instructions: def countdown(number): while number > 0: yield number number -= 1 values = countdown(3) print(next(values, "done")) print(next(values, "done")). Displayed result: 3 2. The final example bindings are countdown --> object 1 (function); values --> object 2 (generator). object 1: function countdown; object 2: <generator object countdown>

Follow the execution

Choose a different sample input, then follow every step through to the output. Before revealing it, predict what the program will display.

Execution workspace

Choose a sample and follow its execution. Guided simulation.

Code
Python
def countdown(number):
    while number > 0:
        yield number
        number -= 1
values = countdown(3)
print(next(values, "done"))
print(next(values, "done"))
Live state

Top-level scope

countdown→Object 1
values→Object 2
Object 1 · functionfunction countdownObject 2 · generator<generator object countdown>
This step

The example has finished. Compare the final output with the values and references above.

Terminal
Output
3
2

What do you expect this program to print?

What does this example display?

def countdown(number):
    while number > 0:
        yield number
        number -= 1
values = countdown(3)
print(next(values, "done"))
print(next(values, "done"))
What does this example display?
Choose one answer. You can try again.

Answer and explanation

3 2

Follow the printed values in order. The output is: 3 2

Which explanation matches what you learned?

Which explanation matches what you learned?
Choose one answer. You can try again.

Answer and explanation

A generator yields values lazily. yield pauses its execution, and the next request resumes it from that point.

A generator yields values lazily. yield pauses its execution, and the next request resumes it from that point.

Introduction to Python Generators

When working with large datasets or continuous data streams, we often seek smarter ways to process information without gobbling up memory. That’s where Python Generators come in — they allow you to iterate lazily, computing values only as needed.

What is a Generator?

A generator is a special type of iterator in Python. It lets you generate values on the fly instead of storing them in memory like lists. You define a generator using a regular function but with a twist — the yield keyword.

Why Use Generators?

  • Efficient memory usage
  • Faster for large or infinite sequences
  • Cleaner code for custom iterators

Creating Your First Generator

Let’s take a simple example to see generators in action.

def count_up_to(n):
    count = 1
    while count <= n:
        yield count
        count += 1

gen = count_up_to(3)
print(gen)  # Just a generator object
for num in gen:
    print(num)
<generator object count_up_to at 0x...>
1
2
3

Explanation

Unlike regular functions, calling a generator function doesn't run it. Instead, it returns a generator object. When used in a for loop, it executes until the next yield is hit — pausing there and resuming from the same spot in the next iteration.

The Power of Lazy Evaluation

Generators don’t compute values until you ask for them. This approach is known as lazy evaluation.

def infinite_numbers():
    num = 0
    while True:
        yield num
        num += 1

gen = infinite_numbers()
for _ in range(5):
    print(next(gen))
0
1
2
3
4

This example shows how generators can theoretically run forever — only producing the next value when needed.

Generator vs List: A Memory Comparison

import sys

def gen_func():
    for i in range(1000):
        yield i

gen_obj = gen_func()
list_obj = [i for i in range(1000)]

print(sys.getsizeof(gen_obj))   # Lightweight
print(sys.getsizeof(list_obj))  # Much heavier
112
9024

Notice how the generator object is tiny in memory compared to the full list — even though they represent the same range of values.

Using Generators with next()

You can manually control a generator using the next() function.

def greeting():
    yield "Hi"
    yield "Hello"
    yield "Hey"

g = greeting()
print(next(g))
print(next(g))
print(next(g))
Hi
Hello
Hey

If you call next() again after it's exhausted, it will raise a StopIteration exception.

Generator Expressions

Much like list comprehensions, Python allows you to create generators in a compact form using generator expressions.

gen_exp = (x * x for x in range(5))
for val in gen_exp:
    print(val)
0
1
4
9
16

They’re shorter to write and just as memory-efficient.

Common Pitfalls and Checks

  • Don't reuse a generator — once exhausted, it's done.
  • Be cautious with infinite generators — always add a break or limit when testing.
  • If you're expecting a return value, note that yield doesn’t return data like return. Use return only when you want to terminate the generator early.

How to Check if an Object is a Generator?

from types import GeneratorType

def sample():
    yield 1

print(isinstance(sample(), GeneratorType))  # True
True

Next Steps

  • Try converting a regular function that builds a list into a generator.
  • Use generators in file reading (line by line) for large files.
  • Explore itertools — many of its tools work seamlessly with generators.

What to remember

Connect what you noticed in the example with the idea below.

Remember

A generator yields values lazily. yield pauses its execution, and the next request resumes it from that point.

Watch out for this idea

Calling a generator function immediately calculates all yielded values.

This is the misconception to avoid.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Python Closures →