1. Home
  2. Docs
  3. Python 201
  4. Iterators

Iterators

  

In this lesson we are going learn about, Iterators

You often here these confusing words,

Iterable, Iterator, Iteration

Let’s break down and understand them.

 

Iteration

 
It’s a repetition of a process, for example when you use for-loop,

you get an item from some thing, do some thing with that, right?
  

for x in something:

	do_something()

  
getting an item and doing something is a process,

which is repeated, until all the items are exhausted.

This is called iteration.

 

Iterable

 

Any object, which allows us to iterate through.

In other words, a Python object which supports Iteration.

In Python, an iterable object, has an __iter__() method implemented,

By this method iterable object is capable of creating an iterator.

 

Built-in iterables

 

Python is full of iterables, You might have already seen lists, tuple,

files, str,dict etc….. they are all iterable.

Which means a list or tuple or a file is capable,

of creating an iterator object.
 

How to check an object is iterable?

 
If you check the names of any iterable with dir(), you will find

__iter__ dunder method. If the object has this method, that means

its an iterable.
 

Ex 1:
  

empty_list = []

dir(empty_list)

output:

#other names are not shown.

[...

'__iter__',

...
]

In simple words, iterable object which capable of creating iterator.

This created iterator works on iterable.

Iterables can be iterated any number of times.

To understand this let’s consider a list

  

list [1,2,3,4,5],

And we will iterate through it twice with for-loop.

  

my_list = [1,2,3,4,5]

print("First iteration")

for i in my_list:

    print(i, end =" ")

print("\nSecond iteration")

for j in my_list:
    
    print(j, end= ' ')


output:

First iteration

1 2 3 4 5 

Second iteration

1 2 3 4 5 


  

Iterator

Iterator is an object, which has ability to iterate,

through each element of an iterable.

Iterable creates iterator, that iterator is used to

iterate through iterable.

In simple words, iterator is Python object, which performs

iteration over iterable.

 

How iterator is created?

They are created by iter() function, internally its __iter__() method.

 
Iterator objects have __next__() implemented,

By using this __next__ method, iterator is able to iterate

through iterables.
 

Iterator knows their current state

 
Iterator objects,know there iteration count,

the count is maintained with internal state variable.

When the iteration reaches the last item StopIteration exception is raised.

Nothing resets the iteration count to zero. Because of this

an iterator can be iterated only once, to understand this

let’s look at the same list example.
  

list [1,2,3,4,5],

  

We will create an iterator by the use of iter() method,
 
and try to iterate through it twice with a for-loop.
  

my_list = iter([1,2,3,4,5])

print("First iteration")

for i in my_list:

    print(i, end =" ")

print("\nSecond iteration")

for j in my_list:
    
    print(j, end= ' ')


output:

First iteration

1 2 3 4 5 

Second iteration


  
Notice we could only access the values during First iteration,

Nothing gets printed in the Second iteration.

Which proves that iterator can only be iterated once.

  

Iteration Protocol

 

Iteration protocol is about how iterables actually work internally.

It’s just a fancy term.

Iteration protocol is combination of next() and iter() method

implementation.

Next we will create our own iterator class, which uses

iteration protocol.

  

Creating user defined iterators

Iterators are implemented as classes, which have __iter__() and __next__()

methods.

Ex 1:

Let’s build an iterator, which returns sequence of numbers.

  

class MyIterator(object):

    def __init__(self, n):

        self.x = 0

        self.n = n

    def __iter__(self):

        return self

    def __next__(self):

        if self.x >= self.n:

            raise StopIteration("Can't go further")
            
        else:

            self.x += 1
            
            return self.x
        

mi = MyIterator(3)

next(mi)

next(mi)

next(mi)

output:

1

2

3

# the next(mi) will throw an exception

next(mi)

output:

---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-27-a4ac8116c79b> in <module>()
----> 1 next(mi)

<ipython-input-24-1298d5b4deeb> in __next__(self)
      9     def __next__(self):
     10         if self.x >= self.n:
---> 11             raise StopIteration("Can't go further")
     12 
     13         else:

StopIteration: Can't go further



  

Ex 2:
 
Let’s create an iterator to get Fibonacci series.

  

class fib_itertor(object):
    
    def __init__(self,n):
    
        self.prev = 0
        
        self.cur = 1
        
        self.number = n

        self.count = 0
        

    def __iter__(self):
        
        return self

    def __next__(self):

        if self.count < self.number:

            self.prev, self.cur = self.cur, self.prev + self.cur
            
            self.count += 1

            return self.prev

           
        else:

            raise StopIteration("Reached desired number")

fb1 = fib_itertor(10)

for fb in fb1:
    
    print(fb, end=" ") 


output:

1 1 2 3 5 8 13 21 34 55 

  

In the next lesson you will learn about, generators,

which is a special type of iterator.