Python Iterators

An iterator is an object that produces its values one at a time, and understanding it explains how Python's for loop actually works.

Python draws a line between two related ideas. An iterable is anything you can loop over, such as a list, tuple, string, or dictionary. An iterator is the object that walks through an iterable and hands back one item each time you ask for the next one. Every time you write a for loop, Python quietly creates an iterator behind the scenes and calls it repeatedly until there is nothing left.

iter() and next()

You turn an iterable into an iterator with the built-in iter() function, then pull values from it with next(). When the iterator runs out of items, next() raises a StopIteration exception, which is the signal a for loop uses to know it should stop.

Stepping through an iterator by hand

colors = ["red", "green", "blue"]
it = iter(colors)

print(next(it))   # red
print(next(it))   # green
print(next(it))   # blue
# print(next(it)) would now raise StopIteration

What a for loop really does

A for loop is simply a convenient wrapper around iter() and next(). The two snippets below behave identically; the loop just hides the exception handling for you.

The for loop, expanded

numbers = [1, 2, 3]

# What you write:
for n in numbers:
    print(n)

# What Python effectively does:
it = iter(numbers)
while True:
    try:
        n = next(it)
    except StopIteration:
        break
    print(n)

Building your own iterator

You can make any class iterable by defining two special methods. __iter__() returns the iterator object itself, and __next__() returns the next value or raises StopIteration when finished. The class below counts up to a limit you choose.

A custom iterator class

class CountUpTo:
    def __init__(self, limit):
        self.limit = limit
        self.current = 1

    def __iter__(self):
        return self

    def __next__(self):
        if self.current > self.limit:
            raise StopIteration
        value = self.current
        self.current += 1
        return value

for number in CountUpTo(4):
    print(number)   # prints 1, 2, 3, 4
TermMeaning
IterableAn object you can loop over, e.g. a list or string
IteratorAn object that returns items one by one via next()
__iter__()Returns the iterator object
__next__()Returns the next value or raises StopIteration
StopIterationThe exception that signals iteration is finished
Note: Iterators produce values lazily, one at a time, so they can represent very large or even endless sequences without storing every item in memory at once. Generators, created with the yield keyword, are a compact way to build iterators without writing __iter__ and __next__ yourself.

Exercise: Python Iterators

Which two special methods must an object define to be an iterator?