Iterators & Iterables in Python. Introduction to Iterators and Iterables | by Sadrach Pierre, Ph.D. | Towards Data Science

In this post, we will discuss python iterators and iterables. We will go over the definitions of each of these objects as well as work towards developing an understanding of the underlying concepts behind each object.
Let’s get started!
Iterables are objects in python that are capable of returning their elements one at a time. Additionally, these objects have a double underscore (also called dunder) method called ‘__iter__()’, where the ‘__iter__()’ method returns an iterator (more on that later). An example of an iterable is a list. To help us understand what it means for lists to be iterable objects, let’s define a list. Let’s define a list that contains the top five best albums of all time according to Rolling Stones:
best_albums = ["Sgt. Pepper’s Lonely Hearts Club Band", "Pet Sounds", "Revolver", "Highway 61 Revisited",  "Rubber Soul"]
The first part of our definition for iterables stated that they allow us to return their elements one by one. Let’s demonstrate this by looping over our list:
for album in best_albums:    print(album)
This feature of iterables is pretty clear. We also specified the ‘__iter__()’ method, which also qualifies a python object as an iterable. We can check the methods and attributes available to our object using the built-in ‘dir()’ method:
print(dir(best_albums))
We can see that the ‘__iter__()’ method is present in the list of methods and attributes for our object . In general, any object with the ‘__iter__()’ method can be looped over.
Further, when we use for-loops on iterables, we call the ‘__iter__()’ method. When the ‘__iter__()’ method is called it returns an iterator.
Now, let’s define iterators.
Iterators are objects with states, where the state specifies the current value during iteration. Iterators also have a dunder method called ‘__next__()’, which allows us to access subsequent values. If we look at the attributes and methods for our list, we can see that there is no ‘__next__()’, which means that lists are not iterators.
We can demonstrate this by trying to use the ‘next’ method on our list:
print(next(best_albums))
We get an error telling us that our list object is not an iterator. Since we know list objects are iterables, meaning they have ‘__iter__()’ methods, we can call ‘__iter__()’ on our list to return an iterator:
iter_best_albums = best_albums.__iter__()
A cleaner and equivalent way to define our iterator is as follows:
iter_best_albums = iter(best_albums)
Let’s print our iterator:
print(iter_best_albums)
We see that our object is indeed an iterator. Now, let’s print the attributes and methods for our iterator object:
print(dir(iter_best_albums))
We can see that our iterator object has the ‘__next__()’ method. Let’s call this method on our iterator:
print(next(iter_best_albums))print(next(iter_best_albums))print(next(iter_best_albums))
We can see that each time we call ‘next’, our object remembered where it left off and the ‘next’ method pointed to the subsequent value. Let’s see what happens if we call ‘next’ until we run out of values. Let’s call next 6 times:
print(next(iter_best_albums))print(next(iter_best_albums))print(next(iter_best_albums))print(next(iter_best_albums))print(next(iter_best_albums))print(next(iter_best_albums))
We can handle this error with a ‘StopIteration’ exception:
while True:    try:        element = next(iter_best_albums)        print(element)    except(StopIteration):        break
We get the same result that we did from looping over our list from earlier. This is essentially what happens under the hood when we loop over lists with for-loops.
I’ll stop here but feel free to play around with the code yourself. If you’re interested in learning more about iterators and iterables, Cory Schafer’s YouTube tutorial is a great resource.
To summarize, in this post we discussed iterables and iterators in python. Iterables are objects that have the method ‘__iter__()’, which returns an iterator object. Iterators are objects that have the method ‘__next()__’ , which allows us to access subsequent values. Further, iterators have information about state during iteration. Put simply, iterators are what’s going on under the hood of every for-loop in python. I hope you found this useful/interesting. The code from this post is available on GitHub. Thank you for reading!