Generator Comprehensions¶
Sum¶
Python has a number of functions that act on iterables. List comprehensions return an iterable so we can pass list comprehensions straight into a one of these functions.
Let’s try out the sum function:
>>> numbers = [1, 2, 3, 4]
>>> sum(numbers)
10
Let’s sum the squares of all of the numbers in our numbers list. We can use a list comprehension:
>>> sum([n ** 2 for n in numbers])
30
Cool!
Generators¶
We can use sum with tuples, sets, and any other iterable:
>>> sum((8, 9, 7))
24
>>> sum({8, 9, 7})
24
Sometimes we don’t really care if a list comprehension returns a list, or some other kind of iterable. When we passed a list comprehension into sum, we only really needed to pass in an iterable, not necessarily a list.
Let’s use a generator expression instead of a list comprehension. We can make a generator expression like this:
>>> squares = (n ** 2 for n in numbers)
>>> squares
<generator object <genexpr> at 0x7f733d4f7e10>
We can use a generator in our sum call like this:
>>> sum((n ** 2 for n in numbers))
30
When our generator expression is already in parentheses, we can leave off the redundant parentheses:
>>> sum(n ** 2 for n in numbers)
30
Generators don’t work like the other iterables we’ve learned about so far.
>>> squares[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'generator' object is not subscriptable
You can not use item indexes to get values from generators.
You also can’t ask generators for their length:
>>> len(squares)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'generator' has no len()
You can loop over generators:
>>> for s in squares:
... print(s)
...
1
4
9
16
But only once:
>>> for s in squares:
... print(s)
...
Generators are single-use iterables. You can get items from a generator by using the built-in next function:
>>> squares = (n ** 2 for n in numbers)
>>> next(squares)
1
>>> next(squares)
4
>>> next(squares)
9
>>> next(squares)
16
>>> next(squares)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
We’ll go into more detail about generators more in a future class.
Iteration Tools¶
Let’s learn some more built-in functions for working with iterators.
If we want to make sure everything in our list conforms to a certain rule, we can use the all function for that.
>>> all(n > 1 for n in numbers)
False
>>> all(n > 0 for n in numbers)
True
If we want to only make sure that some of our list conforms to a certain rule, we can use the any function.
>>> any(n > 2 for n in numbers)
True
>>> any(n < 1 for n in numbers)
False
If we want to find the smallest or largest value in a collection, we can use min or max:
>>> min(numbers)
1
>>> max(numbers)
4