What are iterators in Python?

In Python, objects can be broadly classified into one of the two groups, iterable or non-iterable. If an object is capable of returning its member value one by one its iterable; if it is not capable, it is non-iterable. For non-iterable objects, we have to treat the content as a single unit only; however, an iterable object’s content is like a collection of elements that can be individually traversed. Some common examples of iterable objects are lists, tuples, sets, and dictionaries.

student_list=['Ravi','Shivam','Teja','Rohan']
student_tuple=('Ravi','Shivam','Teja','Rohan')
student_set={'Ravi','Shivam','Teja','Rohan'}
student_dict = {'name': 'Ravi', 'branch': 'CSE',   'year': 3 }

Iterator

Python has a dedicated object called iterators used for iterating over iterable objects. These iterators are implemented using two methods, iter()iter() and next()next(), that are commonly known as iterator protocol. The task of iter()iter() is to initialize the method; whereas, next()next() is used to perform an iteration over the iterable object.

How to use Iterator

Create an iterator

iter()iter() is used to create the iterator over the iterable object. The iterator created is a value extractor that extracts the successive values from the iterable object to that which it is associated.

itr = iter(student_list)

# <list_iterator object at 0x0000022C0D8C0AF0>

Move the iterator

Once the iterator is created, the built-in function next() is used to obtain the next value from the iterator. This value will start from the first element.

next(itr)
# 'Ravi'

The above code will return the first element from the list, i.e., RaviRavi. Similarly, when we call it again, it will return the next element from the list.

next(itr)
# 'Shivam'

If all the values from an iterator have been returned, a subsequent next() call raises a StopIteration exception. Any further attempts to obtain values from the iterator will fail.

In a nutshell we can state that, if we have an iterable object (say pp), then an iterator can be obtained over it using iter(a) and that each next() call over the created iterator will obtain the next value from pp.

Code

student_list = ['Ravi','Shivam','Teja','Rohan']
itr = iter(student_list)
print(next(itr))
print(next(itr))

User Defined Iterators

Python supports user-defined iterators. To build a user-defined iterator, one needs to implement __iter__() and __next__():

  • __iter__() should return the iterator object and initialize if required.
  • __next__() should return the next item in the defined pattern.

Example: Imagine we want to build an iterator that returns the multiple of 5. So, our iterator would start with 5 and each call of next would return its multiple (10,15,20…):

class FiveMultiple:

  def __iter__(self):
    self.num = 5
    return self

  def __next__(self):
    val = self.num
    self.num += 5
    return val

tableiter = iter(FiveMultiple())

print(next(tableiter))
print(next(tableiter))

If the above iterator is called continuously, it will go on through the execution and will not terminate as there is no termination step. Due to this, the above code may also go for an infinite loop. To avoid this, in __next()__ a condition should be specified in __next()__ that, up to that point, only the iterator should run; else, StopIteration should be called. For this, the above definition of next should be modified as shown below:


def __next__(self):
	if(self.num==100):
    	val = self.num
    	self.num += 5
    	return val
    else:
     raise StopIteration

Code

class FiveMultiple:
def __iter__(self):
self.num = 5
return self
def __next__(self):
val = self.num
self.num += 5
return val
tableiter = iter(FiveMultiple())
print(next(tableiter))
print(next(tableiter))