Understanding Python Iterators: Iterators vs Iterable Objects

Learn about Python iterators, objects that implement the iterator protocol with __iter__() and __next__() methods, allowing traversal through a sequence of values. Understand the difference between iterators and iterable objects such as lists, tuples, dictionaries, and sets, and how to obtain iterators using the iter() method.



Python Iterators

An iterator is an object that contains a countable number of values and can be traversed through all these values. In Python, an iterator is an object which implements the iterator protocol, consisting of the methods __iter__() and __next__().

Iterator vs Iterable

Lists, tuples, dictionaries, and sets are all iterable objects. These are containers you can obtain an iterator from using the iter() method:

Example

# Return an iterator from a tuple, and print each value:
mytuple = ("orange", "grape", "melon")
myit = iter(mytuple)

print(next(myit))
print(next(myit))
print(next(myit))
        
Output

orange
grape
melon
        

Strings are also iterable objects, containing a sequence of characters:

Example

# Strings are also iterable objects:
mystr = "grape"
myit = iter(mystr)

print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
        
Output

g
r
a
p
e
        

Looping Through an Iterator

We can also use a for loop to iterate through an iterable object:

Example

# Iterate the values of a tuple:
mytuple = ("orange", "grape", "melon")

for x in mytuple:
  print(x)
        
Output

orange
grape
melon
        

The for loop actually creates an iterator object and executes the next() method for each loop.

Create an Iterator

To create an object/class as an iterator you have to implement the methods __iter__() and __next__() to your object. The __iter__() method must always return the iterator object itself. The __next__() method must return the next item in the sequence.

Example

# Create an iterator that returns numbers, starting with 1, and each sequence will increase by one:
class MyNumbers:
    def __iter__(self):
        self.a = 1
        return self

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

myclass = MyNumbers()
myiter = iter(myclass)

print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
        
Output

1
2
3
4
5
        

StopIteration

The example above would continue forever if you had enough next() statements or if it was used in a for loop. To prevent the iteration from going on forever, we can use the StopIteration statement. In the __next__() method, we can add a terminating condition to raise an error if the iteration is done a specified number of times:

Example

# Stop after 10 iterations:
class MyNumbers:
    def __iter__(self):
        self.a = 1
        return self

    def __next__(self):
        if self.a <= 10:
            x = self.a
            self.a += 1
            return x
        else:
            raise StopIteration

myclass = MyNumbers()
myiter = iter(myclass)

for x in myiter:
    print(x)
        
Output

1
2
3
4
5
6
7
8
9
10