Unlike conventional functions that return only a single result, a generator is a function that produces a sequence of zero or more results.
Generators are a special case of iterators (see Section 24.2, “Iterators: Values that can produce a sequence of
values”), so they can be used as the
controlling iterable in for statements
and the other places where iterators are allowed.
In a conventional function, the body of the function is
executed until it either executes a return
statement, or until it runs out of body statements (which
is the equivalent of a “return None” statement).
By contrast, when a generator function is called, its body is executed until it either has another value to produce, or until there are no more values.
When a function wishes to return the next generated value, it executes a statement of this form:
yield e
where the is any Python expression.
e
The difference between yield and return is that when a return
is executed, the function is considered finished with
its execution, and all its current state diasppears.
By contrast, when a function executes a yield statement, execution of the function
is expected to resume just after that statement, at
the point when the caller of the function needs the
next generated value.
A generator signals that there are no more values by executing this statement:
raise StopIteration
For an example of a generator, see Section 23.10, “The yield statement: Generate one result
from a generator”.
If you are writing a container class (that is, a class
whose instances are containers for a set of values), and
you want to define an iterator (see Section 26.3.17, “__iter__(): Create an iterator”), that method can be a
generator. Here is a small example. The constructor for
class Bunch takes a sequence of values and
stores them in instance attribute .__stuffList. The iterator method .__iter__() generates the elements of the
sequence in order, except it wraps each of them in
parentheses:
>>> class Bunch(object):
... def __init__(self, stuffList):
... self.__stuffList = stuffList
... def __iter__(self):
... for thing in self.__stuffList:
... yield "({0})".format(thing)
... raise StopIteration
...
>>> mess = Bunch(('lobster Thermidor', 'crevettes', 'Mornay'))
>>> for item in mess:
... print item,
...
(lobster Thermidor) (crevettes) (Mornay)
>>> messWalker = iter(mess)
>>> for thing in messWalker: print thing,
...
(lobster Thermidor) (crevettes) (Mornay)