Iterator Pattern

Iterator pattern makes class instance iterable where class needs to implement method which returns an iterator. An iterator again has to implement a method which return values.

Iterable

An iterable requires __iter__ method which returns an iterator. An example is shown below,

class EvenNumbers:
    def __iter__(self):
        return EvenNumberIter(self.start, self.stop)
    def __init__(self, start, stop):
        self.start = start
        self.stop = stop

Iterator

An iterator requires __next__ method which returns values. For example,

class EvenNumberIter:
        def __init__(self, start, stop):
            self.current = start
            self.stop = stop
        def __next__(self):
            even = self.current
            self.current += 2
            if even >= self.stop:
                raise StopIteration
            return even
        def __iter__(self):
            return self;

Using an iterable

We can use an iterable in for loop as use with list, tuples etc.

evens = EvenNumbers(0, 10)
 
for even in evens:
    print(even)

How does it work?

Python provides in built functions iter and next which creates an iterator and gets the next value from iterator respectively. for loop either excepts an indexable instance or an iterable. When an iterable is provided, for gets the iterator from iterable. In each iteration of loop, for calls next.

We can make list also an iterable using function iter as shown below,

items = [1, 2, 3]
for i in iter(items):
    print(i)

References

  1. https://python-patterns.guide/gang-of-four/iterator/