Iteration, Comprehensions, and Generators (Livehacking Screenplay)¶
for
Recap: Sequential Datatypes¶
for i in [1,2,3,4]:
print(i)
$ python code/10-for-recap.py
1
2
3
4
|
|
Primitive Transformation [1,2,3,4]
⟶ [1,4,9,16]
¶
def squares(seq):
ret = []
for i in seq:
ret.append(i**2)
return ret
for i in squares([1,2,3,4]):
print(i)
$ python code/20-squares-func.py
1
4
9
16
|
|
List Comprehension¶
Problem:
function used in one place
… but defined elsewhere
for i in [i**2 for i in [1,2,3,4]]:
print(i)
$ python code/30-squares-comprehension.py
1
4
9
16
|
|
Where does readability end? ⟶ if
clause
for i in [i**2 for i in [1,2,3,4,5,6,7,8,9] if i%2 != 0]:
print(i)
$ python code/40-odd-squares-comprehension.py
1
9
25
49
81
|
|
Larger Input List (Still Allocated)¶
Problem: what about large lists? Say, 10 million elements.
inputlist = []
print('filling input list')
cnt = 0
while cnt < 10000000:
inputlist.append(cnt)
cnt += 1
print('calculating squares')
for i in [i**2 for i in inputlist]:
print(i)
$ python code/50-larger-list.py
filling input list
calculating squares
... numbers ...
|
|
Input List ⟶ range
¶
- Problem: using lists primarily for iteration. Can this be done
better?
print('creating input range')
inputrange = range(10000000)
print('calculating squares')
for i in [i**2 for i in inputrange]:
print(i)
$ python code/60-input-range.py
creating input range
calculating squares
... numbers ...
|
|
Output List ⟶ yield
¶
Problem: still using temporary list in squares()
def squares(seq):
for i in seq:
yield i**2
for i in squares(range(1,5)):
print(i)
$ python code/70-output-yield.py
1
4
9
16
|
|
Generator Function ⟶ Generator Expression¶
- Problem (re-introduced):
squares()
definition and usage are too far apart
for i in (i**2 for i in range(1,5)):
print(i)
$ python code/80-generator-expression.py
1
4
9
16
|
|