Course Progress61%
🍎 Python Advanced Python Topic 61 / 100
⏳ 8 min read

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."

— ShurAI

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:

What Python does when you write for x in my_list:
Step 1
Call iter(my_list) → this calls my_list.__iter__() and returns an iterator object.
Step 2
Repeatedly call next(iterator) → this calls iterator.__next__() and returns the next value each time.
Step 3
When there are no more values, __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:

python
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__:

python
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

Iterable
Has __iter__. Can produce an iterator.
Examples: list, tuple, str, dict, set.

You can loop over it multiple times.
Iterator
Has both __iter__ and __next__. Tracks position.
Examples: iter(list), file objects.

Can only be consumed once.
All iterators are iterables, but not all iterables are iterators

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

python
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?