pvdocs /Python/Iterators

Iterators

An iterator is any object that implements the iterator protocol: __iter__() and __next__().

Iterable vs Iterator

__iter__ __next__
Iterable Yes (returns an iterator) No
Iterator Yes (returns self) Yes
# A list is iterable, not an iterator
lst = [1, 2, 3]
it  = iter(lst)   # create an iterator from the iterable

next(it)  # 1
next(it)  # 2
next(it)  # 3
next(it)  # raises StopIteration

How for Works Internally

for item in iterable:
    ...

# is equivalent to:
it = iter(iterable)
while True:
    try:
        item = next(it)
    except StopIteration:
        break

Custom Iterator

class CountUp:
    def __init__(self, start, stop):
        self.current = start
        self.stop    = stop

    def __iter__(self):
        return self   # the object IS its own iterator

    def __next__(self):
        if self.current >= self.stop:
            raise StopIteration
        value = self.current
        self.current += 1
        return value

for n in CountUp(1, 4):
    print(n)  # 1 2 3

Useful Built-ins That Return Iterators

range(5)          # range object (lazy)
enumerate(lst)    # yields (index, value) pairs
zip(lst1, lst2)   # yields tuples from multiple iterables
map(fn, lst)      # applies fn lazily
filter(fn, lst)   # filters lazily
reversed(lst)     # iterates in reverse

itertools Module

import itertools

itertools.chain([1, 2], [3, 4])        # 1 2 3 4
itertools.islice(range(100), 5)        # 0 1 2 3 4  (first 5)
itertools.cycle([1, 2, 3])             # 1 2 3 1 2 3 ... (infinite)
itertools.count(10, 2)                 # 10 12 14 ... (infinite)
itertools.product("AB", repeat=2)      # AA AB BA BB
itertools.combinations([1,2,3], 2)     # (1,2) (1,3) (2,3)
itertools.permutations([1,2,3], 2)     # (1,2) (1,3) (2,1) ...

Key Interview Points