Introduction
The terms iterable and iterator are often (and wrongfully) used interchangeably in order to describe an object that supports iterations that is an object that allows to iterate over its elements. In fact, iterators and iterables in Python are two distinct concepts that are usually a source of confusion especially for new-comers.
In today’s article we will discuss about the iteration protocol in Python and how iterators and iterables participate in its implementation. Additionally, we will explore the key differences between iterable and iterator objects and provide an example that will help you understand how iterable and iterator objects work in action.
The Iteration Protocol in Python
The iteration protocol is used by all iteration tools in Python and implemented by various object types such as for-loops, comprehensions, maps etc. Essentially, the protocol is consisted of two object types, namely iterable and iterator.
- The iterable object is the one you iterate over its elements
- The iterator object is the one that produces the values during the iteration and it also being returned by the iterable object
In the following sections we are going to see in detail how these two object types work and what they need to implement in order to meet the iteration protocol.
What is an Iterable
In Python, an Iterable is an object that implements the __iter__() method and returns an iterator object or an object that implements __getitem__() method (and should raise an IndexError when indices are exhausted). Built-in iterable objects include Lists, Sets and Strings as such sequences can be iterated over -say- in a for-loop.
Note that the preferred way to implement Iterables in recent Python versions is by implementing __iter__() method. The __getitem__() method is a sort of a legacy functionality that was used prior to modern iterators. But Python still considers objects implementing __getitem__() method as Iterables. This means that if __iter__() is not defined, the Python interpreter will instead use __getitem__(). For more details, you can refer to PEP-234.
To summarise, an Iterable in Python is any object that
- can be iterated over (for instance, you can iterate over the characters of a string or the lines of a file)
- implements
__iter__()method (or__getitem__)and thus it can be called withiter()which returns an Iterator - can appear on the right-hand side of a for loop (
for i in myIterable:)
What is an Iterator
On the other hand, an Iterator in Python is an object that implements the __next__() method in a way that
- the next value of an iterable object is being returned and the state of the iterator gets updated so that it points to the next value
- raises a
StopIterationwhen the elements of the iterable object are exhausted
Additionally, an Iterator is an Iterable itself as it must also implement __iter__() method where it simply returns self.
Every Iterator is also an Iterable, but not every Iterable is an Iterator
Python Iterables and Iterators in action
As we already mentioned, one of the built-in object types that are Iterables is Python List. Now let’s assume that we have the following list of integers, as shown below:
>>> my_lst = [5, 10, 15]
Since my_lst is an iterable, we can run iter() method in order to obtain an iterator object from the iterable:
>>> my_iter = iter(my_lst)
We can verify that my_iter is of type list_iterator:
>>> type(my_iter)
list_iterator
Now since my_iter is an Iterator, it therefore implements __next__() method that will return the next element of the list iterable:
>>> my_iter.__next__()
5
Once the iterator returns the next value following __next__() call, it should alter its state so that it now points the next element:
>>> my_iter.__next__()
10
Note that next(iter_name) is also a valid syntax and equivalent to iter_name.__next__() :
>>> next(my_iter)
15
Now that we reached the last element, the next call to __next__() method should raise a StopIteration which is a requirement that must be met by Iterators that implement the __next__() method:
>>> my_iter.__next__()
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/IPython/core/interactiveshell.py", line 3331, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-8-56d779eb7d74>", line 1, in <module>
my_iter.__next__()
StopIteration
Final Thoughts
In today’s article we discussed about the iteration protocol in Python and how Iterables and Iterators are involved in iterations. Additionally, we discussed about the main characteristics Iterables and Iterators have and introduced their main differences. Finally, we showcased how Iterable and Iterator objects work in action.
In one of my next articles I will be discussing how you can create user-defined Iterators in order to make a user-defined class Iterable.
Become a member and read every story on Medium. Your membership fee directly supports me and other writers you read. You’ll also get full access to every story on Medium.
You may also like






