Comprehensions and the walrus
A comprehension inside another builds a list of lists. Two for clauses in one comprehension flatten instead.
grid = [[1, 2, 3], [4, 5, 6]]
flat = [x for row in grid for x in row]
cols = [[row[i] for row in grid]
for i in range(3)]
print(flat)
print(cols)
squares = (x * x for x in range(4))
print(sum(squares), sum(squares))
print({len(w): w for w in ["ab", "cd"]})- A generator expression is lazy and runs once. The second
sumfinds it already empty, and a function that loops over its argument twice gets the same surprise. - In a dict comprehension a repeated key keeps the last value.
- The loop variable stays inside the comprehension. In a class body, a comprehension cannot see the class's own names, except in its first
for.
The walrus operator
:= assigns a name and returns the value in one expression. It saves computing something twice, as in while (line := f.readline()):. In a comprehension the name binds in the surrounding scope.
import re
words = ["a1", "b", "c22"]
nums = [int(m[0]) for w in words
if (m := re.search(r"\d+", w))]
print(nums)Your task
Write transpose(matrix) returning the columns of a list of equal-length rows as lists, using a comprehension inside a comprehension ([] for an empty matrix). Write spread(values) returning the largest minus the smallest value of any iterable, including a generator. Write valid_numbers(items) returning, as one comprehension, the results of the given to_int that are not None, calling to_int once per item.
The explanation opens here once every check passes.