Iterators

As we saw previously, in Python we use the “for” loop to iterate over the contents of objects:

  1. >>> for value in [0, 1, 2, 3, 4, 5]:
  2. ... print(value)
  3. ...
  4. 0
  5. 1
  6. 4
  7. 9
  8. 16
  9. 25

Objects that can be used with a “for” loop are called iterators. An iterator is, therefore, an object that follows the iteration protocol.

The built-in function “iter” can be used to build iterator objects, while the “next” function can be used to gradually iterate over their content:

  1. >>> my_iter = iter([1, 2, 3])
  2. >>> my_iter
  3. <list_iterator object at 0x10ed41cc0>
  4. >>> next(my_iter)
  5. 1
  6. >>> next(my_iter)
  7. 2
  8. >>> next(my_iter)
  9. 3
  10. >>> next(my_iter)
  11. Traceback (most recent call last):
  12. File "<stdin>", line 1, in <module>
  13. StopIteration

If there are no more elements, the iterator raises a “StopIteration” exception.

Iterator classes

Iterators can be implemented as classes. You just need to implement the “__next__“ and “__iter__“ methods. Here’s an example of a class that mimics the “range” function, returning all values from “a” to “b”:

  1. class MyRange:
  2. def __init__(self, a, b):
  3. self.a = a
  4. self.b = b
  5. def __iter__(self):
  6. return self
  7. def __next__(self):
  8. if self.a < self.b:
  9. value = self.a
  10. self.a += 1
  11. return value
  12. else:
  13. raise StopIteration

Basically, on every call to “next” it moves forward the internal variable “a” and returns its value. When it reaches “b”, it raises the StopIteration exception.

  1. >>> myrange = MyRange(1, 4)
  2. >>> next(myrange)
  3. 1
  4. >>> next(myrange)
  5. 2
  6. >>> next(myrange)
  7. 3
  8. >>> next(myrange)
  9. Traceback (most recent call last):
  10. File "<stdin>", line 1, in <module>
  11. StopIteration

But most important, you can use the iterator class in a “for” loop:

  1. >>> for value in MyRange(1, 4):
  2. ... print(value)
  3. ...
  4. 1
  5. 2
  6. 3

Exercises with iterators

  1. Implement an iterator class to return the square of all numbers from “a” to “b”.

  2. Implement an iterator class to return all the even numbers from 1 to (n).

  3. Implement an iterator class to return all the odd numbers from 1 to (n).

  4. Implement an iterator class to return all numbers from (n) down to 0.

  5. Implement an iterator class to return the fibonnaci sequence from the first element up to (n). You can check the definition of the fibonnaci sequence in the function’s chapter. These are the first numbers of the sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …

  6. Implement an iterator class to return all consecutive pairs of numbers from 0 until (n), such as (0, 1), (1, 2), (2, 3)…