Functional Python Programming

(Wang) #1
Chapter 3

The other limitation of generator functions is that they can only be used once.
For example, look at the following command snippet:





result= pfactorsl(1560)
sum(result)
27
sum(result)
0





The first evaluation of the sum() method performed evaluation of the generator.
The second evaluation of the sum() method found that the generator was now
empty. We can only consume the values once.


Generators have a stateful life in Python. While they're very nice for some aspects
of functional programming, they're not quite perfect.


We can try to use the itertools.tee() method to overcome the once-only limitation.
We'll look at this in depth in Chapter 8, The Itertools Module. Here is a quick example of
its usage:


import itertools
def limits(iterable):
max_tee, min_tee = itertools.tee(iterable, 2)
return max(max_tee), min(min_tee)


We created two clones of the parameter generator expression, max_tee() and
min_tee(). This leaves the original iterator untouched, a pleasant feature that allows
us to do very flexible combinations of functions. We can consume these two clones to
get maxima and minima from the iterable.


While appealing, we'll see that this doesn't work out well in the long run. Once
consumed, an iterable will not provide any more values. When we want to compute
multiple kinds of reductions—for example, sums, counts, minimums, maximums—we
need to design with this one-pass-only limitation in mind.


Combining generator expressions


The essence of functional programming comes from the ways we can easily combine
generator expressions and generator functions to create very sophisticated composite
processing sequences. When working with generator expressions, we can combine
generators in several ways.


One common way to combine generator functions is when we create a composite
function. We might have a generator that computes (f(x) for x in range()).
If we want to compute g(f(x)), we have several ways to combine two generators.

Free download pdf