11 Iterators and generators

 

Have you ever noticed that many Python objects know how to behave inside of a for loop? That’s not an accident. Iteration is so useful, and so common, that Python makes it easy for an object to be iterable. All it has to do is implement a handful of behaviors, known collectively as the iterator protocol.

In this chapter, we’ll explore that protocol and how we can use it to create iterable objects. We’ll do this in three ways:

  1. We’ll create our own iterators via Python classes, directly implementing the protocol ourselves.
  2. We’ll create generators, objects that implement the protocol, based on something that looks very similar to a function. Not surprisingly, these are known as generator functions.
  3. We’ll also create generators using generator expressions, which look quite a bit like list comprehensions.

11.1 What is a for loop?

Even newcomers to Python know that if you want to iterate over the characters in a string, you can write

for i in 'abcd':
    print(i)     #1

This feels natural, and that’s the point. What if you just want to execute a chunk of code five times? Can you iterate over the integer 5?

for i in 5:    #1
    print(i)

Actually, this code doesn’t work. Instead, it produces an error:

TypeError: 'int' object is not iterable

Strings, lists, and dicts are iterable, but integers aren’t. That’s because they don’t implement the iterator protocol, which consists of three parts:

11.2 Python’s iteration protocol

11.3 Making your class iterable

11.4 Other iterators

11.5 Exercise 46 ■ MyEnumerate

11.5.1 Working it out

11.5.2 Solution

11.5.3 Beyond the exercise

11.6 Exercise 47 ■ Circle

11.6.1 Working it out

11.6.2 Solution

11.6.3 Beyond the exercise

11.7 Exercise 48 ■ All lines, all files

11.7.1 Working it out

11.7.2 Solution