Python Arena
Step 3 of 3

Generator expressions

In part 11 you built lists with list comprehensions. Write the same thing in round brackets instead of square ones, and you get a generator expression (also called a generator comprehension): a generator made without writing a function.

squares = (n * n for n in range(1, 6))
print(next(squares))
print(next(squares))
for square in squares:
    print(square)
Output
1
4
9
16
25

Like a generator function, it computes nothing in advance: each value is calculated when it's asked for. next works, a for loop works, and it's used up after one pass. Printing it shows only <generator object <genexpr> at 0x7f3a2c>, but type tells what it is:

In the Python interpreter
>>> squares = (n * n for n in range(1, 6))
>>> type(squares)
<class 'generator'>
>>> sum(squares)
55
>>> sum(squares)
0

The second sum is 0 because the first one already used up every value.

Straight into a function

Functions such as sum, max, min and the string method join accept any series of values, a generator too. When a generator expression is a function's only argument, you can leave out its own brackets. A condition at the end works as it does in list comprehensions:

words = ["generators", "are", "lazy", "and", "thrifty"]
print(sum(len(word) for word in words))
print(max(len(word) for word in words))
print(" ".join(word.upper() for word in words if len(word) > 3))
Output
27
10
GENERATORS LAZY THRIFTY

A list or a generator?

A list comprehension builds the whole list at once and keeps it. Choose it when you need the values more than once, need to know how many there are with len, or need an item by its index. A generator can't do those things:

squares = (n * n for n in range(1, 6))
print(squares[0])
Python stops with
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    print(squares[0])
          ~~~~~~~^^^
TypeError: 'generator' object is not subscriptable

"Not subscriptable" means the value doesn't support []. A generator expression is the better choice when you go through the values just once, especially when there are many: sum(n * n for n in range(1000000)) adds up a million squares without ever storing a list of a million numbers.

Your task

Challenge 1 of 3

Fill in the blank with the value the generator expression gives for each part, so that the program adds up the numbers in the text and prints:

Total: 49

Challenge 2

What does this program print? Type each line it prints.

Challenge 3

Write a function long_words(text, minimum) that returns a generator giving the words of text that have at least minimum letters, in capital letters. Make it with a generator expression. For example,

words = long_words("a lazy generator makes values on demand", 5)
print(next(words))
print(next(words))
print(list(words))

should print:

GENERATOR
MAKES
['VALUES', 'DEMAND']