I've been teaching people to code at the place where I work, and I've come to appreciate the advantages in having relevant examples on hand when explaining concepts.

This is not a post on how iterators work, but rather on an explanation that illustrates their benefits and use.

Recently I was talking about iterators, and needed a simple example to illustrate the benefits around computation. The answer: reversal!

For this example (and all future ones), I'm using the excellent ipython


Say we want to traverse through a large collection in reverse order, but not necessarily traversing all the way to the end. Let's get 1 million integers

In [1]: l = [n for n in range(1_000_000)]

Now, lets just reverse the whole list, then get the first item

In [2]: def rev1(lst):
   ...:     lst.reverse()
   ...:     return lst[0]
   ...:

But remember, the whole list is now reversed, and we might not be wanting to iterate through it all (if this example was exanded to more than just element 0).
How could you make it so that you don't waste calculations on reversing parts that won't be reached? Enter iterators. Instead of reversing the whole collection, we can create an iterative process which we can increment as we please:

In [3]: def rev2(lst):
   ...:     return next(reversed(lst))
   ...:

This means that it only takes a few operations to get the first reversed element! The speed difference is pretty impressive:

In [4]: %timeit rev1(l)
1.01 ms ± 64.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [5]: %timeit rev2(l)
412 ns ± 20.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Until next time!