liveBook · Manning

StopIteration

As explained in Python Workout: 50 ten-minute exercises

StopIteration is the Python exception raised by an exhausted iterator to signal that no further values are available.

StopIteration is the signal that an iterator has no more values. A for loop calls iter() to obtain an iterator, repeatedly calls next(), and exits when __next__ raises StopIteration. section 10.0

A custom iterator usually stores its data and current position, returns itself from __iter__(), and raises StopIteration when the position reaches the data’s length. The exception ends iteration rather than representing an unexpected failure. section 10.2

A finite custom iterator

class LoudIterator: def __init__(self, data): self.data = data self.index = 0 def __iter__(self): return self def __next__(self): if self.index >= len(self.data): raise StopIteration value = self.data[self.index] self.index += 1 return value for item in LoudIterator('abc'): print(item) The loop prints a, b, and c, then stops when the next call raises StopIteration. section 10.0 section 10.2

Keep these distinctions in mind when implementing or using iteration:

  • Iterables provide an iterator through __iter__(); iterators provide values through __next__(). section 10.0
  • A reusable iterable can return a fresh helper iterator instead of returning itself, avoiding exhausted state on a second loop. section 10.2
  • Generator functions raise StopIteration automatically when they finish; use return for early termination rather than explicitly raising it. section 10.15
  • An iterator can repeat or transform values and may stop only after producing a customized number of results. section 10.6
class LoudIterator():
    def __init__(self, data):
        print('\tNow in __init__')
        self.data = data                        #1
        self.index = 0                          #2
 
    def __iter__(self):
        print('\tNow in __iter__')
        return self                             #3
 
    def __next__(self):
        print('\tNow in __next__')
        if self.index >= len(self.data):        #4
            print(
                f'\tself.index ({self.index}) is too big; exiting')
            raise StopIteration
 
        value = self.data[self.index]           #5
        self.index += 1                         #6
        print('\tGot value {value}, incremented index to {self.index}')
        return value
 
 
for one_item in LoudIterator('abc'):
    print(one_item)

Trace __init__, __iter__, __next__, value production, index updates, and the final StopIteration event in a runnable iterator. section 10.0

How Python Workout: 50 ten-minute exercises covers it

How deep it goes
Defines the protocol, traces custom implementation, contrasts helper iterators, and explains generator completion behavior.
Examples
Uses a traced LoudIterator, a helper iterator for repeated loops, generator functions, and a repeating Circle iterator.
What it assumes
Assumes familiarity with Python classes and loops while establishing iterables, iterators, and the iterator protocol.
What you can do after
Build it from scratch by implementing finite, reusable, or repeating Python iterators.
How it connects
Connects iterators with iterables, for loops, generators, next(), __iter__(), and __next__().

Also explained in

Compare how 2 books explain StopIteration →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Python Workout: 50 ten-minute exercises. The section links point to the parts of the book it draws on.