Some list operations also work on iterators. We will now examine the equivalents of list comprehensions and list zipping (refer to section List of Chapter 3, Container Types, for more details).
There is an equivalent of list comprehension for generators. Such a construction is called a generator expression:
g = (n for n in range(1000) if not n % 100) # generator for 100, 200, ... , 900
This is useful in particular for computing sums or products because those operations are incremental; they only need one element at a time:
sum(n for n in range(1000) if not n % 100) # returns 4500
In that code, you notice that the sum
function is given one argument, which is a generator expression. Note that Python syntax allows us to omit the enclosing parentheses of generators when a generator is used as the only argument of a function.
Let us compute the Riemann zeta function ζ, whose expression is
With a generator expression, we may compute a partial sum of this series in one line:
sum(1/n**s for n in itertools.islice(itertools.count(1), N))
Note that we could also have defined a generator of the sequence 1 ⁄ nsas follows:
def generate_zeta(s): for n in itertools.count(1): yield 1/n**s
Then we simply obtain the sum of the first N terms using:
def zeta(N, s): # make sure that you do not use the scipy.sum here return sum(itertools.islice(generate_zeta(s), N))
We point out that we used this way of computing the zeta (ζ) function as a demonstration of the use of generators in an elegant way. It is certainly not the most accurate and computationally efficient way to evaluate this function.
We saw in section List, Chapter 3, Container Types, that it is possible to create a list out of two by zipping them together. The same operation exists for iterators:
xg = x_iterator() # some iterator yg = y_iterator() # another iterator for x, y in zip(xg, yg): print(x, y)
The zipped iterator stops as soon as one of the iterators is exhausted. This is the same behavior as for a zip operation on lists.
18.227.26.217