generator expressions are just like normal list comprehensions, and support all their syntax --
including if filters and loop nesting -- but they are enclosed in parentheses instead of square
brackets.
>>> [x ** 2 for x in range(4)] # List comprehension: build a list
[0, 1, 4, 9]
>>> (x ** 2 for x in range(4)) # Generator expression: make an iterable
<generator object <genexpr> at 0x00000000029A8288>
and
>>> G = (x ** 2 for x in range(4))
>>> iter(G) is G # iter(G) optional: __iter__ returns self
True
>>> next(G) # Generator objects: automatic methods
0
>>> next(G)
1
>>> next(G)
4
>>> next(G)
9
>>> next(G)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Generator expressions vs map
>>> list(map(abs, (−1, −2, 3, 4))) # Map function on tuple
[1, 2, 3, 4]
>>> list(abs(x) for x in (−1, −2, 3, 4)) # Generator expression
[1, 2, 3, 4]
>>> list(map(lambda x: x * 2, (1, 2, 3, 4))) # Nonfunction case
[2, 4, 6, 8]
>>> list(x * 2 for x in (1, 2, 3, 4)) # Simpler as generator?
[2, 4, 6, 8]
and
>>> line = 'aaa,bbb,ccc'
>>> ''.join([x.upper() for x in line.split(',')]) # Makes a pointless list
'AAABBBCCC'
>>> ''.join(x.upper() for x in line.split(',')) # Generates results
'AAABBBCCC'
>>> ''.join(map(str.upper, line.split(','))) # Generates results
'AAABBBCCC'
>>> ''.join(x * 2 for x in line.split(',')) # Simpler as generator?
'aaaaaabbbbbbcccccc'
>>> ''.join(map(lambda x: x * 2, line.split(',')))
'aaaaaabbbbbbcccccc'
Both map and generator expressions can also be arbitrarily nested, which supports general
use in programs, and requires a list call or other iteration context to start the
process of producing results.
>>> [x * 2 for x in [abs(x) for x in (−1, −2, 3, 4)]] # Nested comprehensions
[2, 4, 6, 8]
>>> list(map(lambda x: x * 2, map(abs, (−1, −2, 3, 4)))) # Nested maps
[2, 4, 6, 8]
>>> list(x * 2 for x in (abs(x) for x in (−1, −2, 3, 4))) # Nested generators
[2, 4, 6, 8]