Python – Iterators

Iterators are objects that can be iterated upon. In this tutorial, you will learn how iterator works and how you can build your own iterator using __iter__ and __next__ methods.

 

What is an iterator in Python?

In Python, an iterator is an object with a countable number of elements that can be iterated through. Iterators are objects that allow you to walk through all the elements of a collection and return one element at a time, in simpler terms. An iterator, in more technical terms, is an object that implements the iterator protocol. This protocol will be discussed in more detail in the following section.

Iterator and Iterable

Iterable is a type of object that can be iterated over. When provided to the iter() method, it returns an Iterator. Iterable objects include lists, tuples, dictionaries, strings, and sets. They’re iterable containers that can be turned into iterators.

It’s important to remember that while every iterator is also an iterable, not every iterable is an iterator. A tuple, for example, is iterable but not an iterator. The function iter can be used to build an iterator from an iterable (). As a result, we’ll get an iterator if we provide this tuple to an iter() function. This is possible because an object’s class has a method called __iter__ that returns an iterator.

Which methods are defined in an iterator class in python?

It’s important to remember that while every iterator is also an iterable, not every iterable is an iterator. A tuple, for example, is iterable but not an iterator. The function iter can be used to build an iterator from an iterable (). As a result, we’ll get an iterator if we provide this tuple to an iter() function. This is possible because an object’s class has a method called __iter__ that returns an iterator.

__iter__()

As previously stated, this method returns the iterator object itself. This is essential in order for the for and in statements to work with containers and iterators. The tp iter slot in the type structure for Python objects in the Python/C API corresponds to this method.

__next__()

This function returns the container’s next item. Raise the StopIteration exception if there are no more items. The tp iternext slot in the type structure for Python objects in the Python/C API corresponds to this method.

Here is a simple example, describing these methods:

# define a iterable such as a list
>>> list1 = [0, 1, 2]
# get an iterator using iter()
>>> iter1 = list1.__iter__()
#iertae the item using __next__method
>>> print(iter1.__next__())
0

We may call the __next__ method again to retrieve the next item; in fact, we can call it as many times as we like, and it will always return the iterator’s next item. It throws an error if there are no elements in the iterator to return.

Iterating Through an Iterator

What are the many methods we can traverse the elements of an iterator object so that we only obtain one item at a time now that we have an iterator object? In this part, we’ll look at a few different ways to do so, as well as some examples to help you understand iterators better:

Using the next() function

We can directly use next() function or __next__() method to traverse the elements as shown in the examples below:

# define a iterable such as a list
>>> list1 = [1, 2, 0]
# get an iterator using iter()
>>> iter1 = iter(list1)
# iterate through it using next()
>>> print(next(iter1))
1
# next(obj) is same as obj.__next__()
>>> print(iter1.__next__())
2
>>> print(next(iter1))
0
# This will raise error, no items left
>>> next(my_iter)
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    next(my_iter)

Now let us see how we can traverse a string iterator:

# define a iterable such as a string
>>> string = "hi"
# get an iterator using iter()
>>> iter1 = iter(string)
# iterate through it using next()
>>> print(next(iter1))
h
>>> print(next(iter1))
i
# This will raise error, no items left
>>> next(my_iter)
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    next(my_iter)

Iterating an iterator using while loop and for loop

Why not use a while loop to make our task a little easier because we’re utilizing the next() function so frequently? We’ll also utilize exception handling to handle the error that occurs when the iterator runs out of elements. When the error “StopIteration” occurs, control is passed to the unless block, which executes the break statement. Here’s an illustration:

# define an iterable such as a list
list1=[1,2,3,4,5,6,7,8,9,0]

# get an iterator using iter()
iter1=iter(list1)
# infinite loop
while True:
    try:
        # get the next item
        print(next(iter1))
        # do something with element
    except StopIteration:
        # if StopIteration is raised, break from loop
        break

Output:

1
2
3
4
5
6
7
8
9
0

There is a much easier way to do this also by using a For loop. The for loop does all this under the hood, thus, you don’t need to explicitly call the iter() and next() functions. Here are a few examples:

list1=[1,2,3,4,5,6,7,8,9,0]
for i in list1:
    print(i)
Output:
1
2
3
4
5
6
7
8
9
0

Now let us take some more example:

list2=[1,2,"hello",[9,8,7],(11,12),{'one': 'husaain'}]
for i in list2:
    print(i)
 Output:
1
2
hello
[9, 8, 7]
(11, 12)
{'one': 'husaain'}
string="Hello World "
for i in string:
    print(i)
 
Output:

H
e
l
l
o
 
W
o
r
l
d

Create an Iterator

We’ve only used built-in iterables like lists and strings so far, but in Python, creating an iterator from scratch is simple. All we need to do now is implement the __iter__() and __next__() methods.

Here is our own custom Iterator that returns an even number or 1 every time we iterate upon it:

class Evenit:
 
    def __init__(self, max=0):
        self.max = max

    def __iter__(self):
        self.n = 0
        return self

    def __next__(self):
        if self.n <= self.max:
            if self.n % 2 ==0:
                result=self.n
                self.n += 1
                return result
            else:
                self.n += 1
                return 1
        else:
            raise StopIteration


# create an object
numbers = Evenit(10)

for i in numbers:
	print(i)
Output:
0
1
2
1
4
1
6
1
8
1
10

As we can see, this iterator returns even integers up to ten (since the parameter to the event is ten), and it simply returns one anytime it encounters an odd number. You can make your own iterator in a similar way.

This concludes this tutorial, in which we learned about Python iterators and built our own custom iterator from scratch.

Leave a Comment

Your email address will not be published.