We’ve seen that lists, tuples, strings, and dictionaries can all be used in for loops. These data structures are all iterable. We’ve encountered some more esoteric iterables, too: range, map, and filter all return iterable objects.

Python uses a simple protocol for iterators, with two functions. To make an object iterable, it needs a __iter__(self) method that returns an iterator. An iterator must define __iter__ (typically just returning self) and __next__(self), which either returns the next value or raises StopIteration.

Here’s an example of an iterator that counts by odds up to 100:

Notice how Odds keeps some internal state!