Python iter

Summary: in this tutorial, you’ll learn how to use the Python iter() built-in function effectively.

Introduction to the Python iter function

The iter() function returns an iterator of a given object:

iter(object)Code language: Python (python)

The iter() function requires an argument that can be an iterable or a sequence. In general, the object argument can be any object that supports either iteration or sequence protocol.

When you call the iter() function on an object, the function first looks for an __iter__() method of that object.

If the __iter__() method exists, the iter() function calls it to get an iterator. Otherwise, the iter() function will look for a __getitem__() method.

If the __getitem__() is available, the iter() function creates an iterator object and returns that object. Otherwise, it raises a TypeError exception.

The following flowchart illustrates how the iter() function works:

How Python iter() function works

Python iter() function examples

The following example defines a simple Counter class and uses the iter() function to get an iterator of the counter object:

class Counter:
    def __init__(self):
        self.__current = 0


counter = Counter()
iterator = iter(counter)Code language: Python (python)

It’ll raise a TypeError because the counter object is not an iterable:

TypeError: 'Counter' object is not iterableCode language: Python (python)

The following adds the __getitem__() method to the Counter class:

class Counter:
    def __init__(self):
        self.current = 0

    def __getitem__(self, index):
        if isinstance(index, int):
            self.current += 1
            return self.currentCode language: Python (python)

Because the Counter implements the __getitem__() method that returns an element based on an index, it’s a sequence.

Now, you can use the iter() function to get the iterator of the counter:

counter = Counter()

iterator = iter(counter)
print(type(iterator))Code language: Python (python)

Output:

<class 'iterator'>Code language: Python (python)

In this case, Python creates an iterator object and returns it. Hence, you can use the iterator object to iterate the counter:

for _ in range(1, 4):
    print(next(iterator))Code language: Python (python)

The following adds the CounterIterator class to the Counter class and implement the iterable protocol:

class Counter:
    def __init__(self):
        self.current = 0

    def __getitem__(self, index):
        if isinstance(index, int):
            self.current += 1
            return self.current

    def __iter__(self):
        return self.CounterIterator(self)

    class CounterIterator:
        def __init__(self, counter):
            self.__counter = counter

        def __iter__(self):
            return self

        def __next__(self):
            self.__counter.current += 1
            return self.__counter.currentCode language: Python (python)

How it works.

  • The Counter class implements the __iter__() method that returns an iterator. The return iterator is a new instance of the CounterIterator.
  • The CounterIterator class supports the iterator protocol by implementing the __iter__() and __next__() methods.

When both __iter__() and __getitem__() methods exist, the iter() function always uses the __iter__() method:

counter = Counter()

iterator = iter(counter)
print(type(iterator))Code language: Python (python)

Output:

<class '__main__.Counter.CounterIterator'>
1
2
3Code language: Python (python)

In this example, the iter() function calls the __iter__() method instead of __getitem__() method. That’s why you see the CounterIterator in the output.

The second form of the Python iter() function

The following shows the second form of the iter() function:

iter(callable, sentinel)Code language: Python (python)

The iter(callable,sentinel) will call a callable when the next() method is called.

It’ll return the value returned by the callable or raise the StopIteration exception if the result is equal to the sentinel value.

Let’s take an example to understand how the iter(callable, sentinel) works.

First, define a function that returns closure:

def counter():
    count = 0

    def increase():
        nonlocal count
        count += 1
        return count

    return increase
Code language: Python (python)

The counter() function returns a closure. And the closure returns a new integer starting from one when it’s called.

Second, use the counter() function to show the numbers from 1 to 3:

cnt = counter()

while True:
    current = cnt()
    print(current)
    if current == 3:
        breakCode language: Python (python)

Output:

1
2
3Code language: Python (python)

To make it more generic, you can use an iterator instead.

Third, define a new counter iterator:

class CounterIterator:
    def __init__(self, fn, sentinel):
        self.fn = fn
        self.sentinel = sentinel

    def __iter__(self):
        return self

    def __next__(self):
        current = self.fn()
        if current == self.sentinel:
            raise StopIteration

        return currentCode language: Python (python)

The CounterIterator‘s constructor accepts a callable fn and a sentinel.

The __next__() method returns the value returned by the callable (fn) or raise a StopIteration exception if the return value equals the sentinel.

The following shows how to use the CounterIterator:

cnt = counter()
iterator = CounterIterator(cnt, 4)
for count in iterator:
    print(count)Code language: Python (python)

Output:

1
2
3Code language: Python (python)

Instead of defining a new iterator every time you want to iterate values returned by the callable, you can use the iter(callable, sentinel) function:

cnt = counter()
iterator = iter(cnt, 4)

for count in iterator:
    print(count)
Code language: Python (python)

Output:

1
2
3
Code language: Python (python)

Use Python iter() function to test if an object is iterable

To determine whether an object is iterable, you can check if it implements the __iter__() or __getitem__() method.

However, you can use the iter() function to test if an object is iterable as follows:

def is_iterable(object):
    try:
        iter(object)
    except TypeError:
        return False
    else:
        return TrueCode language: Python (python)

If the object doesn’t implement neither __iter__() method nor __getitem__() method, the iter() function raises the TypeError exception.

The following shows how to use the is_iterable() function:

print(is_iterable([1, 2, 3]))
print(is_iterable('Python iter'))
print(is_iterable(100))Code language: Python (python)

Output:

True
True
FalseCode language: Python (python)

Summary

  • Use the Python iter() function to get an iterator of an object.
Did you find this tutorial helpful ?