liveBook · Manning

__iter__

As explained in Python Workout, Second Edition

The __iter__ method is Python's special method for returning an iterator associated with an iterable object.

When a value works in a for loop, Python asks it for an iterator. The iter built-in performs that request by calling __iter__, whose result supplies values through __next__ until StopIteration ends the loop. Strings, lists, dictionaries, files, and custom objects can participate; integers cannot. section 11.1 section 11.2

Implement __iter__ according to the behavior your object needs:

  • Return self when the object also implements __next__ and should act as its own stateful iterator. section 11.3
  • Return a separate iterator when each new for loop should begin independently, as with strings, lists, tuples, and dictionaries. section 11.5 section 11.7
  • Return any iterator object, including a helper-class instance or generator expression; __iter__ does not have to return self. section 11.11

A repeating iterable

class Circle: def __init__(self, data, max_times): self.data = data self.max_times = max_times def __iter__(self): n = len(self.data) return (self.data[x % n] for x in range(self.max_times)) Circle('abc', 5) produces a, b, c, a, b. The generator expression returned by __iter__ controls the iteration count, while modulus wraps the data index. section 11.11

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 the calls made by a for loop: construction, __iter__, repeated __next__ calls, and the final StopIteration. section 11.3

A return-self implementation is stateful: after one complete pass, its index remains exhausted, so a second pass may produce nothing. Use a helper iterator or generator when the containing object must be reusable. section 11.7 section 11.9

How Python Workout, Second Edition covers it

How deep it goes
Explains dispatch through iter and next, iterator state, StopIteration, helper iterators, and generator-expression alternatives.
Examples
Demonstrates LoudIterator, Circle, MyEnumerate, and repeated iteration over a helper iterator.
What it assumes
Assumes familiarity with for loops and common iterables while teaching the iterator protocol and custom-class implementation.
What you can do after
Build custom iterable classes and diagnose exhausted self-iterators by tracing __iter__, __next__, and StopIteration.
How it connects
Links __iter__ to iterables, iterators, __next__, StopIteration, for loops, and generators.

Also explained in

Compare how 2 books explain __iter__ →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Python Workout, Second Edition. The section links point to the parts of the book it draws on.