Python Iterators

  • Python

In this tutorial, we’ll learn what a python iterator is and how it works. We’ll also learn hot to make our own custom iterator using __iter__() and __next__() methods.

We know that lists, strings, and tuple are iterable objects and we use for loop to iterate over the iterable object. For loop also creates an iterator object in the background and call the next() method on the values. So, an Iterator is an object that we can iterate on.

Method we used previously to iterate over any object :

nums = [1,2,3,4]

for i in nums:
  print(i)

Output :

1
2
3
4

How to Iterate using an Iterator?

Let’s use the same example to understand this. To convert the given list into an iterator, we use iter() function.

nums = [1,2,3,4]

it = iter(nums)
print(it)

We successfully created an iterator using a list called nums and we assigned the iterator a name it. Now, if we run the above code, it will print the object of the iterator. To print values, we need to use an inbuilt method called __next__() and it will print only one value.

nums = [1,2,3,4]

it = iter(nums)
print(it.__next__())

Output :

1

To print more values, we need to use the same method again and instead of printing the first value again, it will print the next value as it preserves the previous state.

nums = [1,2,3,4]

it = iter(nums)
print(it.__next__())
print(it.__next__())

Output ;

1
2

Similarly, this can be performed on a string object and instead of writing __next__(), we can use next() and pass the iterator object as a parameter.

name = "Techie"

it = iter(name)

print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))

Output :

T
e
c
h
i
e

For loop with Iterators

We can also use a for loop to iterate over an iterator.

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

it = iter(nums)

print(next(it))

for i in nums:
  print(i)

Output :

1
1
2
3
4
5

The for loop also executes the next() method but does not use the previous state of the iterator object.

Creating a Custom Iterator

Now we know that an Iterator uses two methods __next__() and __iter__(). Similarly, we’ll implement these methods in our custom iterator in python. The iter() method will give us the iterator and next() method will give us the next values.

Before creating a custom iterator, let’s understand what happens if we try to print values more than that iterable object has.

nums = [1,2,3,4]

it = iter(it)

print(next(it))
print(next(it))
print(next(it))
print(next(it))
print(next(it))

Output :

1
2
3
4
Traceback (most recent call last):
  File "main.py", line 9, in <module>
    print(next(it))
StopIteration

As the next() method reached the end of the list, there was another next() method called and it raised StopIteration exception since there were not more elements. Similarly, the next() method in out custom iterator should include an exception for StopIteration.

class FirstFive:
  
  def __init__(self):
    self.x = 1

  def __iter__(self):
    return self

  def __next__(self):
    if self.x <= 5:
      res = self.x
      self.x += 1
      return res

    else:
      raise StopIteration

result = FirstFive()

for i in result:
  print(i)

Output ;

1
2
3
4
5

In the above example, we’re printing first five values and if it tried to access the sixth value, it will stop the iteration.