Course Outline (Part 22)

An iterator is an object that contains a countable number of values. An iterator is an object that can be iterated upon, meaning that you can traverse through all the values.

Technically, in Python, an iterator is an object which implements the iterator protocol, which consists of the methods __iter__() and __next__().


1. Iterable vs Iterator

Lists, tuples, dictionaries, and sets are all iterable objects. They are iterable containers which you can get an iterator from.

All these objects have an iter() method which is used to get an iterator:

mytuple = ("apple", "banana", "cherry")
myit = iter(mytuple) # Get the iterator

print(next(myit)) # apple
print(next(myit)) # banana
print(next(myit)) # cherry

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

mystr = "banana"
myit = iter(mystr)

print(next(myit)) # b
print(next(myit)) # a

2. Looping Through an Iterator

We can also use a for loop to iterate through an iterable object. The for loop actually creates an iterator object and executes the next() method for each loop implicitly.

mytuple = ("apple", "banana", "cherry")

for x in mytuple:
    print(x)

3. Create a custom iterator

To create an object/class as an iterator you have to implement the methods __iter__() and __next__() to your object.

  • The __iter__() method acts similar, you can do operations (initializing etc.), but must always return the iterator object itself.
  • The __next__() method also allows you to do operations, and must return the next item in the sequence.

Let’s 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)) # 1
print(next(myiter)) # 2
print(next(myiter)) # 3
print(next(myiter)) # 4
print(next(myiter)) # 5

4. 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:

class MyNumbers:
    def __iter__(self):
        self.a = 1
        return self

    def __next__(self):
        if self.a <= 5: # Terminating condition
            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

Because of the StopIteration exception, the for loop knows exactly when to terminate.

Discussion

Loading comments...