Iterators

You don't have to use python for long to come across for loops. You can loop over all sorts of objects in python, lists, dictionaries, strings. Many more specialized objects have methods you can call to loop over. For example, if you have a pandas DataFrame instance, you can use for row in my_df.iterrows() to iterate over its rows.


In [1]:
my_list = [1, 2, 3]
for x in my_list:
    print(x)


1
2
3

But how do they work?

Any object in python can be iterated over if it follows the iteration protocol laid out in PEP 234 (https://www.python.org/dev/peps/pep-0234/). An object should implement a method __iter__ which takes no arguments and returns another object that implements a __next__ method, which returns the next item in the sequence. When the sequence is exhausted, __next__ should raise StopIteration.

In some cases, the object returned by __iter__ may be the same object it was called on (return self), other times, as in the example below, it could be a new object created just for the purpose of iteration.


In [2]:
my_iter = my_list.__iter__()

print("Type:", type(my_iter))

print(my_iter.__next__())
print(my_iter.__next__())
print(my_iter.__next__())


Type: <class 'list_iterator'>
1
2
3

StopIteration

While a for loop will handle the StopIteration exception and know to terminate the loop, if we reach the end of the iterator outside of a for loop, we can see the exception as it's raised.


In [3]:
print(my_iter.__next__())


---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-3-4091dee71d9f> in <module>()
----> 1 print(my_iter.__next__())

StopIteration: 

Don't actually call the __next__ and __iter__ methods though

I showed these methods to display how any object in python can implement the interface. For actual use, Python has builtin functions next and iter that you should use.


In [4]:
my_iter = iter(my_list)
print("Type:", type(my_iter))

print(next(my_iter))
print(next(my_iter))
print(next(my_iter))


Type: <class 'list_iterator'>
1
2
3

In [ ]: