Convert Python Object to Iterator

Convert Python Object to Iterator

  1. Use the __iter__() and __next__() Method to Convert Object to Iterator in Python
  2. Properties of Iterators in Python
  3. Conclusion

Iterators in Python are those items that we will loop through, or in other words, iterate upon. We can change any object to an iterator or even make our iterators with the help of __iter__() and __next__() methods.

It is useful when we have to access some objects as iterators. We can do that using generator loops, but those are time-consuming and make the code bulky.

Python’s in-built method __iter__() is better for such tasks.

Use the __iter__() and __next__() Method to Convert Object to Iterator in Python

As the name suggests, an iterator returns the data values one by one. The iterator object does this with the help of the __iter__() and the __next__() method.

The __iter__() and __next__() method together form the iterator protocol. Let us discuss some examples to understand the basic working of the iterator protocol.

demo = ("volvo", "ferrari", "audi")
val = iter(demo)

print(next(val))
print(next(val))
print(next(val))

Output:

volvo
ferrari
audi

Here, we have a tuple with three values. We use the __iter__() method to get the values from this tuple object one by one.

Further, the __next__() method iterates through these values one after one. We can use the __next__() method differently, like this.

demo = ("volvo", "ferrari", "audi")
val = iter(demo)

print(val.__next__())
print(val.__next__())
print(val.__next__())

Output:

volvo
ferrari
audi

Now also we get the same output. PEP 3114 changed iterator.next() to iterator.__next__(). We can use these methods with any iterable object.

Here is an example that uses strings.

demostr = "volvo"
val = iter(demostr)

print(next(val))
print(next(val))
print(next(val))
print(next(val))
print(next(val))

Output:

v
o
l
v
o

Python has many built-in containers that are iterable - strings, lists, tuples. We can use the __iter__() function to create objects from iterables.

Further, we can use the __next__() method to access objects one by one.

Syntax:

iter(object_name)
iter(callable, sentinel)

Here, the object_name refers to the object like list or tuple whose iterator will be created. Further, callable refers to a callable object, and sentinel refers to the value that gives the termination condition of the iteration.

The sentinel value shows the end of the sequence that we are iterating. Thus, if we call the iterator when all objects have already been iterated, we get the StopIterationError exception.

Note that creating iterators does not change the iterable object. Look at this example which demonstrates the StopIterationError.

li = ['volvo', 'ferrari', 'audi']

value = li.__iter__()
print(value.__next__())
print(value.__next__())
print(value.__next__())
print(value.__next__())  #Error occurs here

Output:

volvo
ferrari
audi

StopIteration

We can even create our object or class as an iterator. Let us create an iterator that will return a sequence of numbers, starting from 10, where each value will be increased by 2.

class GetNumbers:
  def __iter__(self):
    self.x = 10
    return self

  def __next__(self):
    a =  self.x
    self.x += 2
    return a

myclass = GetNumbers()
value = iter(myclass)

print(next(value))
print(next(value))
print(next(value))
print(next(value))
print(next(value))

Output:

10
12
14
16
18

Here, the __iter__() method works like the __init__() method. We can do initialization or operations inside the __iter__() method, but we always return the object.

We can perform operations with the help of the __next__() method. But in that case, the return value should be the next element of the sequence.

Here, we add 2 to each value inside the __next__() method.

Properties of Iterators in Python

There are some properties of iterators that we should know to understand the internal working. These are as follows:

  1. The iteration object uses an internal count variable to keep the iteration count.
  2. We cannot reassign this iteration count variable to 0 again once the iteration is done. Thus, the StopIteration error occurs.
  3. Thus, we can say that the iteration count variable can traverse a container only once.

Here is the link to documentation that talks about iterators in Python.

Now let us look at situations where the iteration never ends. A point noteworthy here is we are using the __next__() method a set number of times.

But what if the iterator object never exhausts? In such a case, writing the __next__() statement many times will not be possible.

We use the iter() method with two arguments. The first argument is callable, and the second argument is a sentinel.

Therefore, when the returned value matches the sentinel, the iterator stops. Paste the below code in your editor and try to run it.

int()
value = iter(int, 1)
next(value)

Output:

>>> 1
1
>>> 1
1
>>> 2
2
>>> 3
3
>>>

When you run this code, you will see that the iterator never stops. It’s because the int() function returns 0 each time.

No matter what value you give as the input, the returned value will never be the same as the sentinel, that is 1 here. Try changing the value of sentinel to 0.

int()
value = iter(int, 0)
next(value)

Output:

StopIteration

This time, we get the StopIteration exception on the first run itself.

The way we created our iterators, we can also create our infinite iterators. Let us make an infinite iterator that will return a list of all even numbers.

class Even:
    def __iter__(self):
        self.x = 0
        return self
    def __next__(self):
        x = self.x
        self.x += 2
        return x

Output:

>>> obj = iter(Even())
>>> next(obj)
0
>>> next(obj)
2
>>> next(obj)
4
>>>

The biggest advantage of using iterators is that they help us save resources. Note that a lot of space would have been wasted if we used variables.

But with the help of iterators, we can get all even numbers without worrying about storing them in memory.

To learn more about iterator objects in Python, refer to this documentation.

Conclusion

In this article, we discussed the concept of iterators in Python. We talked about the working of the __iter__() and __next__() method and some examples.

We also saw how the use of iterators is memory efficient when we want to work with infinite values. We also made our iterators using the iterator protocol.

Related Article - Python Iterator

  • Python Custom Iterator
  • Differentiate Iterator and Generator in Python