Python Iterators
Think of an iterator as an object holding a countable set of values that you can step through, one value at a time, until you have visited them all.
What makes an object an iterator in Python is a rule known as the iterator protocol: the object must provide two methods, __iter__() and __next__().
Iterator vs Iterable
A list, tuple, dictionary or set is an iterable: a container that can hand you an iterator when you ask for one.
To ask, pass the container to the built-in iter() function:
Example
iter() and next().
Create a tuple with "apple", "banana", "cherry".
Output: complete Python program
mytuple = ("apple", "banana", "cherry")
myit = iter(mytuple)
print(next(myit))
print(next(myit))
print(next(myit))
Example
iter() and next().
Print each character one by one.
Output: complete Python program
mystr = "banana"
myit = iter(mystr)
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
Looping Through an Iterator
A for loop gives you a shorter way to walk through any iterable:
Example
Output: complete Python program
mytuple = ("apple", "banana", "cherry")
for x in mytuple:
print(x)
Example
Output: complete Python program
mystr = "banana"
for x in mystr:
print(x)
Create an Iterator
Your own class becomes an iterator once you give it both __iter__() and __next__().
The Python Classes/Objects chapter explains __init__(), the function every class has for setting things up at the moment an object is created.
__iter__() plays a similar role: it may do setup work, but its return value must always be the iterator object itself.
__next__() can run operations too, and each call has to hand back the following item in the sequence.
Example
MyNumbers that implements __iter__() and __next__().
The iterator returns numbers starting with 1, increasing by one each time.
Print the first 5 values using next().
Output: complete Python program
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))
StopIteration
Nothing stops the iterator from the previous example: with enough next() calls, or inside a for loop, it would never end.
The way to end it is the StopIteration exception.
Put a condition inside __next__() that raises this exception once the iteration has run as many times as you want:
Example
MyNumbers with __iter__() and __next__() that returns numbers 1 through 20.
Use StopIteration to stop after 20 iterations. Print all values using a for loop.
Output: complete Python program
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myclass = MyNumbers()
myiter = iter(myclass)
for x in myiter:
print(x)