Introduction to Python Iterators

What are Iterators?

An iterator in Python refers to an object that we can iterate upon. The iterator consists of countable values, and it is possible to traverse through these values, one by one.

The iterator simply implements the Python's iterator protocol. The iterator protocol is a Python class which comes with two special methods, namely __iter__() and __next__(). With these two methods, the iterator is able to compute the next value in the iteration.

With iterators, it is easy for us to work with sequences of items in Python. We don't have to allocate computing resources to all the items in the sequence, rather we iterate upon single item at a time which helps us save the memory space.

In this article, we will study how to work with iterators in Python.

Iterable Objects in Python

An iterable is an object capable of returning an iterator. An iterable can represent both finite and infinite data sources. The iterable directly or indirectly implements the two methods: __iter__() and __next__(). The __iter__() method returns the iterator object while the __next__() method helps us traverse the elements in the iterable object.

Examples of iterable objects in Python include Lists, dictionaries, tuples, and sets.

Creating an Iterator

In Python, we create an iterator by implementing the __iter__() and __next__() methods on the object. Consider the following example:

We have created an iterator named element that prints numbers from 0 to N. We first created an instance of the class and we gave it the name classinstance. We then called the iter() built-in method and passed the name of the class instance as the parameter. This creates the iterator object.

Let us now discuss how to use an iterator to actually iterate through the items.

Iterating through an Iterator

The next() method helps us iterate through the elements of an iterator. Let us demonstrate this with the example given above:

In the script above, we called the next() method and passed the name of the iterator element to the method as the parameter. Every time we do this, the iterator moves to the next element in the sequence. Here is another example:

And the above chain can continue forever. This shows that with an infinite iterator, we can have an infinite number of items without having to store all of them in the memory.

In the next section, we will see how we can implement a mechanism to break out of such infinite iterators.

Stopping an Iteration

In the previous section, we saw how to create an infinite iterator in Python. However, iterators are not usually meant for infinite iteration in Python. It is always convenient to implement a terminating condition.

We can stop an iterator from executing forever using the StopIteration statement. We only need to add a terminating condition in the __next__() method which will raise an error once the specified number of iterations has been reached. Here is an example:

The execution halts after 5 iterations. This is because of the self.x <= 5: condition added within the __next__() method. If the iterator is called after reaching 5, it will raise StopIteration event. Consider the example given below:

The terminating condition has been implemented in the following section of our code:

if self.x <= self.max:
val = 3 ** self.x

We passed a value of 3 to the iterator, meaning that the iterator should not iterate beyond 27, that is, 3^3.

Conclusion

Iterators are extremely useful, especially if you need to iterate through a large sequence of items. Iterators allow you to iterate through a sequence of items one at a time without having to load all the items in to memory at once.

In this article, we saw how to create iterators in Python and how to iterate through items in an iterator. We also saw how to create an infinite iterator and how to add terminating condition to an infinite iterator.