5.13 Generator Expressions

A generator expression is similar to a list comprehension, but creates an iterable generator object that produces values on demand. This is known as lazy evaluation. List comprehensions use greedy evaluation—they create lists immediately when you execute them. For large numbers of items, creating a list can take substantial memory and time. So generator expressions can reduce your program’s memory consumption and improve performance if the whole list is not needed at once.

Generator expressions have the same capabilities as list comprehensions, but you define them in parentheses instead of square brackets. The generator expression in snippet [2] squares and returns only the odd values in numbers:


In [1]: numbers = [10, 3, 7, 1, 9, 4, 2, 8, 5, 6]

In [2]: for value in (x ** 2 for x in numbers if x % 2 != 0):
   ...:     print(value, end=' ')
   ...:
9 49 1 81 25

To show that a generator expression does not create a list, let’s assign the preceding snippet’s generator expression to a variable and evaluate the variable:


In [3]: squares_of_odds = (x ** 2 for x in numbers if x % 2 != 0)
In [3]: squares_of_odds
Out[3]: <generator object <genexpr> at 0x1085e84c0>

The text "generator object <genexpr>" indicates that square_of_odds is a generator object that was created from a generator expression (genexpr).

tick mark Self Check

  1. (Fill-In) A generator expression is _____—it produces values on demand.
    Answer: lazy.

  2. (IPython Session) Create a generator expression that cubes the even integers in a list containing 10, 3, 7, 1, 9, 4 and 2. Use function list to create a list of the results. Note that the function call’s parentheses also act as the generator expression’s parentheses.
    Answer:

    
    In [1]: list(x ** 3 for x in [10, 3, 7, 1, 9, 4, 2] if x % 2 == 0)
    Out[1]: [1000, 64, 8]