Home/Learn/Python A–Z/The Iteration Protocol — iter() & next()

The Iteration Protocol — iter() & next()

Intermediate
Iterators & Decorators

Every for loop is sugar over iter() and next(): an iterable produces an iterator, the iterator yields items until StopIteration — implement two dunders and your class joins in.

Overview

Understanding what for actually does unlocks half of advanced Python. An ITERABLE is anything that returns an iterator from __iter__ (lists, dicts, files, ranges); an ITERATOR is the stateful cursor with __next__ that produces values and raises StopIteration when done. Iterators are consumed once and are themselves iterable. This protocol is why generators, zip, map and files all compose — they all speak the same two-method language.

What for Really Does

for x in obj calls iter(obj) once, then next() repeatedly, catching StopIteration to stop. You can drive it manually — and see why iterators exhaust.

iter/next/StopIteration — the machinery under for
nums = [10, 20, 30]

it = iter(nums)          # list (iterable) -> list_iterator
print(next(it))          # 10
print(next(it))          # 20
print(next(it))          # 30
# next(it)               # StopIteration!
print(next(it, "END"))   # 'END' — default instead of raising

# The for loop, desugared:
it = iter(nums)
while True:
    try:
        x = next(it)
    except StopIteration:
        break
    print(x)

# Iterators exhaust — a big source of bugs
pairs = zip([1, 2], ["a", "b"])
print(list(pairs))       # [(1,'a'), (2,'b')]
print(list(pairs))       # [] — already consumed!

Writing Your Own Iterator

Implement __iter__ (return self) and __next__ (return a value or raise StopIteration). Compare with the 4-line generator version — the reason generators exist.

Manual iterator vs generator — same protocol
class Countdown:
    def __init__(self, start):
        self.current = start
    def __iter__(self):
        return self
    def __next__(self):
        if self.current <= 0:
            raise StopIteration
        self.current -= 1
        return self.current + 1

for n in Countdown(3):
    print(n)              # 3 2 1

# The same thing as a generator — Python writes the class for you:
def countdown(start):
    while start > 0:
        yield start
        start -= 1

print(list(countdown(3)))  # [3, 2, 1]

# Iterable vs iterator in one line:
# iterable: has __iter__ (can be looped many times, e.g. list)
# iterator: has __next__ too (a one-shot cursor, e.g. generator)

Key Points to Remember

  • 1Iterable = has __iter__; iterator = also has __next__ and exhausts
  • 2for = iter() once + next() until StopIteration
  • 3next(it, default) avoids the exception
  • 4zip/map/filter/file objects are one-shot iterators — materialize with list() if you need reuse

Interview Questions

Sign in to ask Aria
1

Difference between an iterable and an iterator? Which is a list, which is a generator?

MediumAmazon
2

Desugar a for loop into while + iter + next.

MediumMicrosoft
3

Why does iterating the same zip object twice give an empty result the second time?

MediumPaytm

Ask Aria about The Iteration Protocol — iter() & next()

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…