Data structures · Lesson 9 of 18 · 16 min
Comprehensions
List, set, dict, and generator expressions as a dialect.
- Rewrite map/filter loops as comprehensions
- Know when a generator expression is enough
- Avoid nested comprehension soup
A comprehension is a loop in expression form
`[f(x) for x in xs if p(x)]` builds a list. `{f(x) for x in xs}` builds a set. `{k: v for k, v in pairs}` builds a dict. The `if` is a filter, not an `else`. There is no comprehension ternary besides the ordinary `x if cond else y` in the value position.
A generator expression `(f(x) for x in xs)` is lazy: it produces values as you iterate. `sum(n * n for n in range(1000))` never builds the list of squares. Wrapping in `[]` would.
words = ["Ada", "alan", "Py", "lambda"]
print([w.lower() for w in words if len(w) > 2])
print({w[0].lower() for w in words})
print({w: len(w) for w in words})
gen = (len(w) for w in words)
print(gen, list(gen), list(gen))Nesting and flattening
Two `for` clauses flatten: `[x for row in matrix for x in row]`. Read them in the same order you would write nested for-loops. If you have to squint, write the loops. Clarity beats cleverness; a comprehension with two filters, a walrus, and a nested call is usually a function.
Dict comprehensions overwrite duplicate keys. `{c: i for i, c in enumerate('abba')}` keeps the last index of each letter.
matrix = [[1, 2], [3, 4]]
print([x for row in matrix for x in row])
print({c: i for i, c in enumerate("abba")})Check yourself
Quiz
1.`(n for n in range(3))` is a:
2.After `g = (x for x in [1]); list(g); list(g)` the second list is:
3.Filter in a comprehension uses:
Practice
Exercise
Write `squares(n)` returning a list of squares of 0..n-1, and `odds(xs)` returning a new list of the odd numbers in xs.
Tutor
Ask a question about this lesson. Answers are generated on demand and capped so the session stays focused.