Python iterators are used to iterate through a collection of items. However, unlike loops, Python iterators iterate through items one at a time. There are two ways to use iterators in Python. You can use built-in Python iterators, or you can create your custom Python iterators. In this article, you will study and implement both these iterator types with the help of different examples. So, let’s begin without ado.

  1. Built-in Python  Iterators
  2. Custom Python  Iterators
  3. Custom Python  Iterators with a Stop Condition

Python Iterators

Built-in Python  Iterators

With Python built-in iterators is the easiest way to use iterators. Let’s see how Python built-in iterators work.

Create a simple list of items by executing the following script:

colors = ["red", "green", "blue", "orange"]

In the script above we create a Python list with 4 items.

To create a built-in iterator in Python, you just have to pass a collection of items to the iter() method as shown in the following script:

color_iterator = iter(colors)

Let’s now try to check the type of the color_iterator object:

type(color_iterator)

Output:

list_iterator

You can see that the type of the color_iterator object now is list_iterator.

There are two ways to iterate over an iterator in Python. You can either call __next__() method from an iterator object or you can pass the iterator object to the next() method. Let’s see examples of both of these methods.

Iteration using __next()__ Method

To iterate over a list via iterator, you can call __next__() method. Let’s iterate through the color_iterator object that we created earlier.  Execute the following script:

print(color_iterator.__next__())

Once you execute the above script, the first item of the colors list will be printed as shown below:

 

When you call the __next__() method on an iterator for the first time, the first item from the iterator list is returned and the cursor moves to the second item. Now if you call __next__() method again, the second item of the list is returned. Likewise, you can return all the items from an iterator by calling __next__() method multiple times as shown below:

print(color_iterator.__next__())
print(color_iterator.__next__())
print(color_iterator.__next__())

Output:

green
blue
orange

If you call the __next__() method after all the items in an iterator are returned, you will see the following error:

---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-8-2cbf9482838e> in <module>
----> 1 print(color_iterator.__next__())

StopIteration:

It is important to mention that, an iterator cannot be reset. Once you have iterated through all the items in an iterator, you cannot go back to a previous item. You have to create a new iterator if you wish to iterate through a collection of items again.

Let’s now see how you can iterate through a collection via an iterator using the next() method.

Iteration using __next()__ Method

With the next() method, you just have to pass the iterator object as a parameter to the method. Let’s see an example. The following script creates an iterator even_iterator that iterates through a list of first five even numbers.

evens = [2,4,6,8,10]

even_iterator = iter(evens)

Let’s return the first item of the even_iterator. Run the following script:

print(next(even_iterator))

Output:

2

Similarly, you can iterate through the remaining items in the iterator via the following script:

print(next(even_iterator))
print(next(even_iterator))
print(next(even_iterator))
print(next(even_iterator))

Output:

4
6
8
10

Again, if you call the next() method after all the items have been iterated, you will see the following error:

---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-13-61ba235d821e> in <module>
----> 1 print(next(even_iterator))

StopIteration: 

 

Custom Python  Iterators

In addition to the built-in Python iterators, you can define your own Python iterators as well. Let’s see an example of how to do this. An iterator is essentially a Python object. Thus, to create a Python object, you need to define a Python class. Inside the class, you need to define two methods: __iter__() and __next__(). In the next example, you will create an iterator that starts from an integer value that you pass to the constructor of the iterator object. Upon calling next() on the iterator, the starter value is incremented by two and returned to the calling function.  Look at the following script:

class MyIterator:

    def __init__(self, starter):
        self.num = starter

    def __iter__(self):
        return self

    def __next__(self):

        num = self.num

    self.num = num + 2;
    return self.num - 2

In the script above, you create a class MyIterator.  The class constructor initializes the instance variable num by the value passed as a constructor parameter. The __iter__() method is called when you initialize the object of the class. The __iter__() method basically defines that this class is an iterator. Finally, the increment or decrement logic is defined inside the __next__() method. In the __next__() method of the MyIterator class, you define that increment the num variable by 2 and return the resulting value. The resulting value is subtracted by 2 so that you can get the initial iterator value as well.

Let’s create an object of MyIterator and initialize it with a random integer value. Subsequently, calling the next() method on the MyIterator class object will increment the existing iterator value by 2 and will return the result. Here is an example:

odd_iterator = MyIterator(5)

print(next(odd_iterator))

Output:

5

The above script initializes the iterator with an integer value of 5. After that, it calls the next() method which returns 7 i.e. initial value plus 2.

Similarly, you can call the next() method thrice on the odd_iterator object to retrieve the next three items in our iterator.

print(next(odd_iterator))
print(next(odd_iterator))
print(next(odd_iterator))

Output:

7
9
11

 

Custom Python  Iterators with a Stop Condition

You can also use the Python loops to iterate through iterators. However, to iterate a custom iterator through loops, you will need to define a stop condition on your iterator otherwise loop will keep iterating through your iterator forever subsequently crashing your system memory. Modify the MyIterator object that you created in the previous section as follows:

class MyIterator: 

    def __init__(self, starter): 
        self.num = starter

    def __iter__(self): 
        return self

    def __next__(self):

        num = self.num

        self.num = num + 2; 

        if self.num > (20 + 2):
            raise StopIteration
        else: 
            return self.num - 2

 

In the script above, you add a condition inside the __next__() method that if the value of the num variable becomes greater than 20, step the iteration. Let’s test the following code.

odd_iterator = MyIterator(5)

for num in odd_iterator:
print(num)

Once you execute the above script, you will see the integers from 5 to 19 printed on the console

Output:

5
7
9
11
13
15
17
19

The output shows that the iterator starts from the value 5 and ends at the value 19.