Iterators
Contents
What is an Iterator
iter()
An Iterator is an object that can iterate over an iterable object.

Let’s look at a couple of examples.
age = 21
iterable = iter(age)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-15-1fc80fbe7676> in <module>
1 age = 21
----> 2 iterable = iter(age)
TypeError: 'int' object is not iterable
What does the error say ? int object is not iterable. Let’s try the same with a list.

odd_numbers = [1,3,5,7,9]
i = iter(odd_numbers)
This time there is no error. What is the difference ? Earlier we were trying to iterate over an integer ( which is not iterable ), while this time we are iterating over a list ( which is iterable).
Essentially, think of an iterable object like a list – something with multiple elements (unlike simple objects like integers or floats). Even simple strings are iterable ( it has multiple characters strung together, isn’t it ). We will see all of these examples in a bit. But the question you might have now is, what to do with this iterator ? What is the purpose of an iterator ?

next()
The primary purpose of an iterator is to iterate over the elements in the object it is pointing to. And how exactly do we do it ? Using the Python’s built-in next ( ) function. Each call to the next ( ) function returns the subsequent element in the iterable object. For example, each subsequent next ( ) call returns the next element in the list. See example below.

print ( next(i) ) # first
print ( next(i) ) # second
print ( next(i) ) # third
print ( next(i) ) # fourth
print ( next(i) ) # fifth
1
3
5
7
9
What happens when you reach the end ? Python throws a StopIteration exception.

next(i)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-12-a883b34d6d8a> in <module>
----> 1 next(i)
StopIteration:
Of course, lists are not the only iterable objects. Even simple strings are iterable – each time returning the next element when the next ( ) function is called.
name = "Ajay Tech"
iterable = iter(name)
print ( next(iterable) ) # first
print ( next(iterable) ) # second
print ( next(iterable) ) # third
print ( next(iterable) ) # fourth
print ( next(iterable) ) # fifth .. and so on
A
j
a
y
What about dictionaries ?
names = { "Ajay" : 21,
"Stacy": 22}
iterable = iter(names)
print ( next(iterable) ) # first
print ( next(iterable) ) # second
Ajay
Stacy
Why does a dictionary iterable just return the keys ? Well, that’s how the Python dictionary class is defined. We will see in a bit how to define our own iterable classes.
The same logic applies for tuples & sets as well.
names = ("Ajay","Stacy") # tuple
iterable = iter(names)
print ( next(iterable) ) # first
print ( next(iterable) ) # second
Ajay
Stacy
names = {"Ajay","Stacy"} # set
iterable = iter(names)
print ( next(iterable) ) # first
print ( next(iterable) ) # second
Ajay
Stacy
Build your own iterable class
An iterator is an object that implements the next method. An iterable is an object that implements the iterand next methods. That was geeky enough – let’s try to create a simple iterable class. We know what a Fibonacci series is already. Let’s create a Fibonacci iterable class that outputs the next Fibonacci number.

class Fibonacci :
def __init__ (self, max = 100):
self.max = max
def __iter__ (self) :
self.first = 0
self.second = 1
return self
def __next__ (self):
self.return_value = self.first
if self.first > self.max :
raise StopIteration
self.third = self.first + self.second
self.first = self.second
self.second = self.third
return self.return_value
f = iter(Fibonacci())
print ( next(f) ) # first
print ( next(f) ) # second
print ( next(f) ) # third
print ( next(f) ) # fourth
print ( next(f) ) # fifth
print ( next(f) ) # sixth and so on..
0
1
1
2
3
5
What you have here is an enhanced version of a Fibonacci class that can act as an iterable. Of course you can define a function in it that returns all the fibonacci numbers, but if you want them in a sequence this is how you do it.
For loop over an iterable
Of course, you can’t be issuing print statements every time. The primary purpose of an iterable is to get the next element. So, obviously it makes sense that it would be very suitable with a for loop. In fact for loop internall works by calling the iterable methods.

Let’s see if our Fibonacci class works with a for loop.
fib = Fibonacci()
for f in fib :
print ( f )
0
1
1
2
3
5
8
13
21
34
55
89
Yay!! it worked.