Python 3.14 ·
✓ verified by execution on 2026-07-28
Iterators and Generators
The Iterator Protocol
Every for loop in Python is really the iterator protocol at work: iter() to get an iterator, then next() repeatedly until it signals it is finished. Lists, files, dicts and strings all speak it, which is why one loop shape works on all of them.
Iterators are the objects behind Python’s for loops. We can manually step through them using iter() and next():
Because it is a protocol rather than a base class, your own classes can join in: implement __iter__ and __next__ and your object works in a for loop like anything built in.
When an iterator is exhausted, calling next() raises a StopIteration exception:
A generator does the same job with far less ceremony. Each yield hands back a value and freezes the function — local variables, position, everything — so the next next() resumes exactly where it stopped.
Here is an IP01 interactive visualizer that shows how the generator pauses at each yield and resumes exactly where it left off, saving its state:
Click to view state suspension visualizer
python · visualize
def stateful_generator(): print("Starting") yield 1 print("Resuming") yield 2gen = stateful_generator()print("Before first next()")print(next(gen))print("Before second next()")print(next(gen))
Generator Expressions
For one-liners there is the generator expression: the same syntax as a list comprehension, but with parentheses. It produces values on demand instead of building the whole list up front.
Instead of a full function, you can create quick generators using generator expressions:
python
squares_gen = (x * x for x in range(4))for sq in squares_gen: print(sq)
Output
0
1
4
9
Your output
Challenges
Complete the interactive challenges below to earn XP!
Check yourself
Is the following statement true or false? 'Generators load all their values into memory at once like a list.'
Reveal answer
False — Generators use lazy evaluation, producing values one at a time on demand, making them highly memory efficient for large datasets.
Is the following statement true or false? 'You can reuse a generator multiple times.'
Reveal answer
False — Generators are exhausted after they are iterated through once. To iterate again, you must create a new generator object.
Is the following statement true or false? 'A generator function returns a value immediately when called.'
Reveal answer
False — Calling a generator function returns a generator object. It does not begin execution until next() is called.
Challenges
Challenge 1 +25 XP
Write a generator function `even_numbers(max_val)` that yields even numbers from 0 up to `max_val` (inclusive).
python
Test 1 — expects "0\n2\n4\n"
Need a hint? (−25% XP)
Use a for loop and the modulo operator % to check if a number is even, then yield it.
Show solution (0 XP)
def even_numbers(max_val): for i in range(max_val + 1): if i % 2 == 0: yield ifor num in even_numbers(4): print(num)
Challenge 2 +25 XP
Use a generator expression to create an iterator named `cubes_gen` that yields the cube of numbers from 0 to 3.
python
Test 1 — expects "0\n1\n8\n27\n"
Need a hint? (−25% XP)
The syntax for a generator expression uses parentheses: (expression for item in iterable).
Show solution (0 XP)
cubes_gen = (x**3 for x in range(4))for cube in cubes_gen: print(cube)