Python — Iterators
Every for loop uses this protocol
for x in [10, 20, 30]:
print(x)
Under the hood:
it = iter([10, 20, 30]) # 1. get an iterator from the iterable
next(it) # 2. pull values one at a time → 10
next(it) # 20
next(it) # 30
next(it) # 💥 StopIteration → for catches it & ends
| Term | Meaning | Examples |
|---|---|---|
| Iterable | can produce an iterator (iter() works) | list, str, dict, file, range |
| Iterator | the thing being pulled (next() works); remembers position | what iter() returns |
Iterators are consumed — once exhausted they stay empty:
it = iter([1, 2])
list(it) # [1, 2]
list(it) # [] — already spent!
Building your own class-based iterator
class Countdown:
def __init__(self, start):
self.n = start
def __iter__(self):
return self # the object is its own iterator
def __next__(self):
if self.n <= 0:
raise StopIteration
self.n -= 1
return self.n + 1
for n in Countdown(3):
print(n) # 3, 2, 1
The duet: __iter__ returns the iterator; __next__ produces the next value or raises StopIteration.
Generators — iterators without ceremony
yield turns any function into a generator (an iterator factory):
def countdown(start):
while start > 0:
yield start # pause here, hand out a value
start -= 1
for n in countdown(3):
print(n)
Same behavior as the class above with a tenth of the code. State persists between yields automatically.
Why generators matter: laziness
Values are produced ON DEMAND — nothing exists until asked:
def squares():
n = 1
while True: # infinite!
yield n * n
n += 1
sq = squares()
next(sq) # 1
next(sq) # 4
next(sq) # 9 — an infinite series in finite memory
Reading huge files line-by-line, streaming API data, infinite sequences — all generator territory.
Handy iteration tools
nums = [5, 3, 8]
sum(nums); max(nums); min(nums) # consume any iterable
sorted(nums, reverse=True)
reversed(nums) # lazy reverse iterator
# itertools — iteration superpowers
from itertools import count, chain
chain([1], [2, 3]) # 1,2,3 across containers
count(10, step=2) # infinite: 10,12,14…
Gotchas: reusing a spent iterator silently yields nothing ·
next(it)on empty raises unless you pass a default:next(it, None).
Mini Practice
- Manually iter/next a string; catch StopIteration.
- Prove exhaustion by consuming twice.
- Class-based Fibonacci iterator.
- Rewrite it as a generator; compare lines of code.
- Infinite even-numbers generator + islice to take five.
Next: polymorphism →
Related Topics
Frequently Asked Questions about Iterators
What is Iterators in Python?
Iterators is a fundamental concept in Python. This lesson explains it step by step with clear examples, making it easy for beginners to understand.
How do I learn Iterators?
Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Iterators.
Why is Iterators important in Python?
Iterators is essential for Python development. Understanding this concept will help you write better code and solve real-world problems more effectively.