Types of iterators in Python, Which One to Use?

In this Article we will write

  • code for various iterators in python

  • comparing the time taken by the iterator to iterate

  • when to use which iterator

if you're new to this topic, i would prefer you go with this article linked below first:-*

Types of Iterators in Python

  1. Forward Iterator (for iterator)
  2. Reverse Iterator
  3. Index Based Iterator
  4. Enumerate Iterator
  5. Parallel Iterator
  6. File Iterator
  • Forward Iterator
  1. It is a read-only iterator, means you can only travese over it items in iterable, cannot modify values
  2. It is the fastest way to iterate/traverse over the iterable (Collection on values)
  3. As it's name suggest it can move only forward, going at the previous element is not possible.

Example :-

>>> names = ['ram','shyam','ajay','bipin','manoj','alex']
>>> for name in names:
...     name = name.upper()
...     print(name)
...
RAM
SHYAM
AJAY
BIPIN
MANOJ
ALEX
>>> names
['ram', 'shyam', 'ajay', 'bipin', 'manoj', 'alex']

As we can see in the above example for loop uses forward iterator,to iterable over the name in the names list,
we also tried to modify each value, by explicitly assigining
it to new uppercase value but, it does not modifiy the name in the names list, as we can see on the last line
.

  • Reverse Iterator
  1. It is a read-only iterator, means you can only travese over it items in iterable, cannot modify values
  2. Iterate over element in the reverse order ,starting from last element to first element in the iterable.
  3. it has same efficiency as forward itertor
  4. reversed() function is used to return list_reverseiterator object

Example :-

>>> names
['ram', 'shyam', 'ajay', 'bipin', 'manoj', 'alex']
>>> reverse_iter = reversed(names)
>>> reverse_iter
<list_reverseiterator object at 0x000001D28CA21D20>
>>> for name in reverse_iter:
...     print(name)
...
alex
manoj
bipin
ajay
shyam
ram
>>>

The reversed object return list_reverseiterator object which then traveres from last element to first element.

  • Index Based Iterator
  1. It uses a special function -

    • range(start,stop,stepby),
    • range(start,stop),
    • range(stop)
  2. Suitable when we have to perfrom read/write operation on the iterable object.

  3. Suitable for INPLACE list operations

  4. It is slower compared to for iterator

Example :-

>>> names = ['ram','shyam','ajay','bipin','manoj','alex']
>>> for i in range(len(names)):
...     names[i] = names[i].upper()
...     print(names[i])
...
RAM
SHYAM
AJAY
BIPIN
MANOJ
ALEX
>>> names
['RAM', 'SHYAM', 'AJAY', 'BIPIN', 'MANOJ', 'ALEX']

As you can see we used range() function to traverse/iterate over the list using index, and also able to modify the value INPLACE.

  • Enumerate Iterator
  1. It uses a special function -

    • enumerate(iterable), return enumerate object
  2. Suitable for Mutable iterable objects

  3. Can be used for INPLACE Operations

  4. Slow as compared to forward Iterator

Example :-

>>> names = ['ram','shyam','ajay','bipin','manoj','alex']
>>> names_iter = enumerate(names)
>>> names_iter
<enumerate object at 0x000001D28CA413C0>
>>> for index,value in names_iter:
...     names[index] = value.upper()
...
>>> names
['RAM', 'SHYAM', 'AJAY', 'BIPIN', 'MANOJ', 'ALEX']

enumerate() function return enumerate object which iterate over a list of tuples where

  1. first element of each tuple is it's corresponding index
  2. second element is the value at store at the index
  3. with the help of index we can modify the value in the names list
  • Parallel Iterator
  1. It uses a special function -

    • zip(iter1, iter2, iter3, iter4....)
  2. Suitable when we have to iterate over mutile iterable object at the same time.

  3. Return zip object

Example :-

>>> first_names = ['ram','shyam','ajay','bipin','manoj','alex']
>>> last_names = ['gupta','tiwari','yadav','rawat','desai','khan','raven']
>>> home_town = ['ayodhya','vrindavan','bihar','jhnasi','boston','delhi','lanka']
>>>
>>> detail_iter = zip(first_names, last_names,home_town)
>>> detail_iter
<zip object at 0x000001D28CA41B00>
>>> for detail in detail_iter:
...     print(detail)
...
('ram', 'gupta', 'ayodhya')
('shyam', 'tiwari', 'vrindavan')
('ajay', 'yadav', 'bihar')
('bipin', 'rawat', 'jhnasi')
('manoj', 'desai', 'boston')
('alex', 'khan', 'delhi')

zip() function return zip object which iterate over a list of tuples where tuples size is equal to the no. of list passed in the zip() function

  • also, it will return list of tuples of size equal to the length of (minimum size iterable among all the iterables passed in the zip() function) i.e
    • first_names list has length of 6
    • last_names list has length of 6
    • home_town list has length of 7

So, it return list of tuples with list size 6

  • File Iterator
  1. It uses a special function -

    • open(filename)
  2. It is used to iterate over the contents of the file

Example :-

File Content :- 
Details :-
('ram', 'gupta', 'ayodhya')
('shyam', 'tiwari', 'vrindavan')
('ajay', 'yadav', 'bihar')
('bipin', 'rawat', 'jhnasi')
('manoj', 'desai', 'boston')
('alex', 'khan', 'delhi')

Code :-

>>> for line in open("hello.txt"):
...     print(line)
...
Output :-

Details :-

('ram', 'gupta', 'ayodhya')

('shyam', 'tiwari', 'vrindavan')

('ajay', 'yadav', 'bihar')

('bipin', 'rawat', 'jhnasi')

('manoj', 'desai', 'boston')

('alex', 'khan', 'delhi')

It reads only line at a time

Now, that we have covered all the 6 iterators, we now see when to use which iterator

When to Use Which Iterator?

when we need to :-

  • traverse on a TUPLE (readonly) - forward iterator

  • traverse on a LIST (readonly) - forward iterator

  • traverse modify list inplace - index based iterator

  • traverse mutiple iterable (readonly) - parallel iterator

Comparing Performance of Iterators

Now, we will going to compare performance of

  • (forward iterator, reverse iterator, index based iterator, enumerate iterator)
  • by iterating a list of size 10000
  • comparing the time taken by various iterator

Example :-

Code :- 
import time
lst = [i for i in range(10000000)]
print("Traversing over list of size 10000000 \n-----------------------------------------------------\n")

start_time = time.time()
for i in lst:
     print("",end="")
end_time = time.time()
print(f"Time take by forward iterator {round(end_time - start_time ,2)} Seconds")

##################################################################

start_time = time.time()
for i in reversed(lst):
     print("",end="")
end_time = time.time()
print(f"Time take by reverse iterator {round(end_time - start_time ,2)} Seconds")


##################################################################

start_time = time.time()
index_based_iter = range(len(lst))
for i in index_based_iter:
     print("",end="")
end_time = time.time()
print(f"Time take by index based iterator {round(end_time - start_time ,2)} Seconds")


##################################################################

start_time = time.time()
index_based_iter = range(len(lst))
for i in index_based_iter:
     print("",end="")
end_time = time.time()
print(f"Time take by enumerate iterator {round(end_time - start_time ,2)} Seconds")


Output :-
Traverseing over list of size 10000000
-----------------------------------------------------

Time take by forward iterator 6.99 Seconds
Time take by reverse iterator 7.45 Seconds
Time take by index based iterator 8.32 Seconds
Time take by enumerate iterator 7.15 Seconds

Now, we have some to end, hope you all are now fimilar with various types of iterators in python and when to use which iterator.
See you next time , covering some other topic :-)

20