Iterators & the Iterator Protocol
Iterators are objects that produce values one at a time. Every for loop uses iterators behind the scenes. Learn the __iter__ and __next__ protocol.
15 min•By Priygop Team•Updated 2026
Iterators
Iterators
# Every iterable has an iterator
nums = [1, 2, 3]
iterator = iter(nums) # get iterator
print(next(iterator)) # 1
print(next(iterator)) # 2
print(next(iterator)) # 3
# next(iterator) # StopIteration!
# Custom iterator class
class Countdown:
def __init__(self, start):
self.start = start
def __iter__(self):
self.current = self.start
return self
def __next__(self):
if self.current <= 0:
raise StopIteration
value = self.current
self.current -= 1
return value
for num in Countdown(5):
print(num, end=" ") # 5 4 3 2 1
print()
# Infinite iterator
class InfiniteCounter:
def __init__(self, start=0):
self.n = start
def __iter__(self): return self
def __next__(self):
value = self.n
self.n += 1
return value
counter = InfiniteCounter()
for _ in range(5):
print(next(counter), end=" ") # 0 1 2 3 4
print()Tip
Tip
Use generator expressions for memory efficiency: sum(x**2 for x in range(1M)) uses almost no memory vs a list comprehension.
Diagram
Loading diagram…
itertools = memory-efficient iteration. All return iterators (lazy). Use chain for flattening. combinations for combinatorics.
Common Mistake
Warning
Generators can only be iterated ONCE. After exhaustion, they produce nothing. Store results in a list if you need to iterate multiple times.
Quick Quiz
Practice Task
Note
(1) Create a Fibonacci generator. (2) Use a generator expression for filtering. (3) Chain generators for a data pipeline.