Understand the contract
An iterable can provide an iterator through iter(). An iterator holds traversal state and produces one value at a time through next(). Lists are reusable iterables: asking a list for a new iterator starts an independent traversal.
An iterator implements __iter__ returning itself and __next__ returning the next item. Once no items remain, __next__ raises StopIteration. A for loop uses this protocol and handles normal exhaustion for you.
Follow the runtime behavior
Advancing an iterator changes its state. Consuming it with list or a loop leaves it exhausted; an exhausted iterator should continue raising StopIteration. next(iterator, default) returns the default at exhaustion instead of raising.
One-pass iterators are useful for streams, but sharing one between consumers means they share progress. To repeat a traversal, keep the original reusable collection or create a fresh iterator from a factory.
Apply it and practise
Use a custom iterator when an object needs explicit traversal state; use a generator function when yield expresses the same sequence more simply. Avoid building a whole list when values can be processed incrementally.
Exercise: implement an iterator yielding 0, 2, 4 and then stopping. Verify iter(iterator) is iterator, consume two values with next, then collect the remainder. Confirm that a second list call is empty.
Syntax
iterator = iter(values)
item = next(iterator)Examples
Advance and exhaust
Use next with a default when reading a possibly empty stream one item at a time.
iterator = iter([10, 20])
print(next(iterator))
print(next(iterator))
print(next(iterator, "done"))
print(list(iterator))- Each next consumes one element. The third call uses its default because the iterator is exhausted, and list finds no remaining values.
- Use next with a default when reading a possibly empty stream one item at a time.
- Choose a default distinguishable from legitimate elements if callers must detect exhaustion unambiguously.
- Expected output: 10 20 done []
Create independent traversals
Use independent iterators when two consumers need to traverse the same stable collection.
values = ["a", "b"]
first = iter(values)
second = iter(values)
print(next(first))
print(next(first))
print(next(second))
print(first is iter(first))- The list creates two different iterators with independent positions. Asking first for its own iterator returns first itself, which is the iterator protocol rule.
- Use independent iterators when two consumers need to traverse the same stable collection.
- Mutating the collection while traversing can complicate the result; this example deliberately leaves it unchanged.
- Expected output: a b a True
Implement a finite iterator
Use a stateful iterator to expose a finite sequence without storing every value.
class Countdown:
def __init__(self, start):
self.remaining = start
def __iter__(self):
return self
def __next__(self):
if self.remaining <= 0:
raise StopIteration
value = self.remaining
self.remaining -= 1
return value
counter = Countdown(3)
print(list(counter))
print(list(counter))- __next__ saves the current count, decrements state, and returns the saved value. At zero it raises StopIteration, so both subsequent traversals remain exhausted.
- Use a stateful iterator to expose a finite sequence without storing every value.
- Countdown is its own iterator and is therefore not restartable; create another instance to repeat the sequence.
- Expected output: [3, 2, 1] []
Best practices
- One-pass iterators are useful for streams, but sharing one between consumers means they share progress. To repeat a traversal, keep the original reusable collection or create a fresh iterator from a factory.
- Use a custom iterator when an object needs explicit traversal state; use a generator function when yield expresses the same sequence more simply. Avoid building a whole list when values can be processed incrementally.
Runtime & versions
Python interpreter. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
Python language reference