⚡ Key Constraint:O(n) time, O(n) memory (materialises) — the generator is the O(1)-memory lazy alternative.
📝 Core
1. The Comprehension (Set-Builder Syntax)
Form ➔ [expr for x in iterable if condition] ➔ mirrors {3x:x∈{0..9}} as [3*x for x in range(10)].
Declarative ➔ the alternative to map/filter (HOFs).
Materialises ➔ builds the whole list (O(n) memory); body should be a pure-ish transform/filter — side-effecting comprehensions are an anti-pattern (use a loop).
⚙️ Core Implementation
🔹 Transform, filter, nest — and the three forms
comprehension vs HOF vs generator
A = [3*x for x in range(10)] # transform: [0,3,6,...,27]C = [x for x in A if x % 2 == 0] # filter: [0,6,12,18,24]M = [[r*c for c in range(3)] for r in range(3)] # nested[f(x) for x in xs if p(x)] # comprehension — eager list, O(n) spacelist(map(f, filter(p, xs))) # HOF form — same result(f(x) for x in xs if p(x)) # GENERATOR expr — lazy, O(1) space, single-pass
💡 Common Mistake:All three are O(n)time ➔ the comprehension uses O(n) memory (materialised, reusable, indexable), the Generator ExpressionO(1) (lazy, single-pass) — pick the generator when you iterate once or the source is huge.
When It Flips: comprehensions are concise and faster than an equivalent append loop (C-optimised list-building) but materialise everything; deeply nested comprehensions hurt readability — fall back to loops.
📊 Exam Execution Trace
Manual Execution Trace
[x for x in range(6) if x % 2 == 0]:
Step / State
x
x%2==0?
Emit
0 (Init)
—
—
[]
1
0, 2, 4
yes
kept
2
1, 3, 5
no
dropped
result
—
—
[0, 2, 4]
Applied Exercise
Problem: Show a comprehension equals map∘filter.
Derivation Proof / Hand-Calculation Walkthrough: