12 · List comprehensions
Transform and filter sequences in one readable line — including a ReLU implementation in three tokens.
`[expr for x in iter if cond]` replaces a 4-line for-loop with a single declarative expression that reads like English: "a list of *expr* for every *x* in *iter* where *cond*".
Without this:
Without comprehensions, every feature transformation or filtering step requires 3–4 lines of for-loop boilerplate — slowing down exploratory data work and making pipelines harder to read.
A list comprehension is a compact way to build a list from any iterable. The basic form [expr for x in iter] applies expr to every element. Adding if cond after the for clause acts as a filter — only elements for which the condition is truthy end up in the result.
Python (in browser)
The comprehension and the for-loop produce identical results. The comprehension is not just shorter — it signals *intent*: this is a pure transformation with no side effects.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
You can embed a ternary expression inside a comprehension to map values differently depending on a condition. This is the Python equivalent of NumPy's clip or the neural network activation function ReLU (Rectified Linear Unit): clamp negative values to zero.
Python (in browser)
Notice how `[x if x > 0 else 0 for x in activations]` reads exactly like the mathematical definition of ReLU: "x if x > 0, otherwise 0".
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
The normalization expression `(x - mean) / std` is the exact z-score formula applied element-wise — the same operation NumPy does with `(arr - arr.mean()) / arr.std()`.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Read outer-to-inner: the outer `for _ in range(rows)` iterates over rows; the inner builds each row. Note `[[0] * cols] * rows` would be a bug — all rows would share the same list object.
What does `[x for x in [1, 2, 3] if x > 1]` return?
Build a suite of comprehensions in the Arena — transformations, filters, and a mini feature-normalizer.
Comprehensions naturally express the element-wise operations on vectors that MML chapter 1 formalises — scalar multiplication, addition, and mapping a function over a vector are all one-liner comprehensions in Python.
- `[expr for x in iter]` transforms every element; `[expr for x in iter if cond]` also filters. Both return a new list.
- A ternary inside a comprehension — `[x if x > 0 else 0 for x in vals]` — maps values through a two-way condition (ReLU pattern).
- Keep comprehensions short (1–2 lines). For complex multi-step logic, a regular `for` loop is more readable.
Feature normalization: `[(x - mean) / std for x in features]`. Activation functions: `[max(0, x) for x in layer_output]`. Label filtering: `[s for s, l in zip(scores, labels) if l == 1]`. These patterns appear constantly in data-prep scripts before NumPy or Pandas enters the picture.
If you remove it: Without comprehensions, every feature transformation or label-filter step requires a 4-line loop. In exploratory work you might write dozens of such loops — comprehensions compress that cognitive load significantly.