Iterators
Peek under the hood of the for loop — how Python’s iterator protocol really works with __iter__ and __next__.
"Every time you write for item in something, Python quietly calls two dunder methods under the hood. Understanding them demystifies loops forever."
What Happens Inside a for Loop?
A for loop works with any iterable — something Python can loop over. But how? Under the hood, Python uses two special methods every single time:
for x in my_list:iter(my_list) → this calls my_list.__iter__() and returns an iterator object.next(iterator) → this calls iterator.__next__() and returns the next value each time.__next__ raises StopIteration — the loop ends cleanly.Seeing it Manually
You can call iter() and next() yourself to see exactly what the for loop does:
fruits = ["apple", "banana", "cherry"]
# Step 1 — get an iterator from the list
it = iter(fruits)
# Step 2 — call next() to get values one at a time
print(next(it)) # apple
print(next(it)) # banana
print(next(it)) # cherry
print(next(it)) # StopIteration! — loop would end here
Building Your Own Iterator
Make a class iterable by implementing __iter__ and __next__:
class Countdown:
"""Counts down from start to 1."""
def __init__(self, start):
self.current = start
def __iter__(self):
return self # the object itself is the iterator
def __next__(self):
if self.current < 1:
raise StopIteration # signal: no more values
value = self.current
self.current -= 1
return value
for n in Countdown(5):
print(n, end=" ")
# 5 4 3 2 1
Iterable vs Iterator
__iter__. Can produce an iterator.Examples: list, tuple, str, dict, set.
You can loop over it multiple times.
__iter__ and __next__. Tracks position.Examples: iter(list), file objects.
Can only be consumed once.
A list is iterable (you can loop it) but not an iterator (no __next__). Call iter(my_list) to get an iterator from it. Generators (next lesson) are iterators built the easy way.
Real Example — Infinite Even Number Stream
class EvenNumbers:
"""Generates even numbers starting from start. Infinite!"""
def __init__(self, start=0):
self.current = start if start % 2 == 0 else start + 1
def __iter__(self):
return self
def __next__(self):
val = self.current
self.current += 2
return val # never raises StopIteration — infinite!
evens = EvenNumbers(10)
for n in evens:
if n > 20:
break
print(n, end=" ")
# 10 12 14 16 18 20
"Once you understand __iter__ and __next__, you understand every for loop ever written in Python. Lists, files, databases — they all work this same way."
— ShurAI🧠 Quiz — Q1
What does Python call first when you start a for loop on an object?
🧠 Quiz — Q2
How does a for loop know when to stop?
🧠 Quiz — Q3
What is the difference between an iterable and an iterator?
🧠 Quiz — Q4
What does iter(my_list) return?