reference
5 min read
·
lesson 8 of 16 in Reference
Python Comprehensions Cheat Sheet
1 · The lesson
readQuick reference for list, set, dict, and generator comprehensions. For the full tutorial see Comprehensions.
1. The Four Comprehension Forms
| Form | Syntax | Result type | Example output |
|---|---|---|---|
| List | [expr for x in it] | list | [1, 4, 9] |
| Set | {expr for x in it} | set | {1, 4, 9} |
| Dict | {k: v for x in it} | dict | {'a': 1, 'b': 2} |
| Generator | (expr for x in it) | generator (lazy) | <generator object ...> |
python
nums = [1, 2, 3, 4] print([n**2 for n in nums]) # [1, 4, 9, 16] print({n**2 for n in nums}) # {16, 1, 4, 9} print({n: n**2 for n in nums}) # {1: 1, 2: 4, 3: 9, 4: 16} print(sum(n**2 for n in nums)) # 30 (gen exp, no brackets needed in call)
2. Filtering with if
A trailing if filters items:
python
nums = [-2, -1, 0, 1, 2] positives = [n for n in nums if n > 0] # [1, 2] evens = [n for n in nums if n % 2 == 0] # [-2, 0, 2]
Multiple filters chain:
python
[n for n in range(50) if n % 2 == 0 if n % 3 == 0] # [0, 6, 12, 18, 24, 30, 36, 42, 48]
3. Conditional in the Result (if/else)
A conditional expression in the value position transforms; it does not filter:
python
nums = [-2, -1, 0, 1, 2] clipped = [x if x > 0 else 0 for x in nums] # [0, 0, 0, 1, 2]
Position matters:
| Position | Form | Effect |
|---|---|---|
After for ... in | [x for x in xs if cond] | Filter |
Before for | [x if cond else y for x in xs] | Transform |
4. Nested Comprehensions
Build a matrix (rows of rows):
python
matrix = [[r * c for c in range(1, 4)] for r in range(1, 4)] # [[1, 2, 3], [2, 4, 6], [3, 6, 9]]
5. Flattening
The order of for clauses reads left-to-right like nested loops:
python
matrix = [[1, 2, 3], [4, 5, 6]] flat = [item for row in matrix for item in row] # [1, 2, 3, 4, 5, 6] # Filter while flattening odds_flat = [n for row in matrix for n in row if n % 2] # [1, 3, 5]
6. Walrus Operator (3.8+)
Capture an intermediate result inside the comprehension:
python
data = ["12", "x", "7", "y", "5"] nums = [v for s in data if (v := s if s.isdigit() else None) is not None] # Cleaner: collect parsed values without parsing twice import re matches = [m.group() for s in ["a1", "b", "c3"] if (m := re.search(r"\d", s))] # ['1', '3']
setup added so this can run · defines v, m
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) v = _AutoMock('v') m = _AutoMock('m')
7. Generator Expressions
Lazy; iterate once. Perfect for streaming pipelines:
python
total = sum(n * n for n in range(10**6)) # no million-element list built big = max((line.count("x") for line in open("file.txt")), default=0)
Drop the outer parens when passing as the sole argument to a function.
8. Dict Comprehension Tricks
python
# Swap keys and values d = {"a": 1, "b": 2} inv = {v: k for k, v in d.items()} # {1: 'a', 2: 'b'} # Filter by value scores = {"a": 90, "b": 55, "c": 72} passing = {k: v for k, v in scores.items() if v >= 60} # Build from two iterables keys, vals = ["x", "y", "z"], [1, 2, 3] d = {k: v for k, v in zip(keys, vals)} # or dict(zip(keys, vals))
Common Patterns
python
# Dedup while preserving order — use dict trick for old Pythons, set otherwise unique = list({x: None for x in items}) # Flatten a matrix flat = [c for row in matrix for c in row] # Swap dict swapped = {v: k for k, v in d.items()} # Filter dict by value big = {k: v for k, v in counts.items() if v > 10} # Build dict from two lists d = {k: v for k, v in zip(keys, vals)} # Counter-like grouping (use collections.Counter for real work) counts = {ch: s.count(ch) for ch in set(s)} # Conditional transform labels = ["pos" if x > 0 else "neg" if x < 0 else "zero" for x in nums] # Cartesian product pairs = [(a, b) for a in xs for b in ys]
setup added so this can run · defines matrix, nums, xs, ys, items, keys, vals, s
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] nums = [3, -1, 4, -1, 5] xs = ["alpha", "beta", "gamma"] ys = ["alpha", "beta", "gamma"] items = ["alpha", "beta", "gamma"] keys = _AutoMock('keys') vals = _AutoMock('vals') s = _AutoMock('s')
Common Errors
| Error / Symptom | Cause | Fix |
|---|---|---|
(1, 2, 3) expected but got generator object | Parens around comprehension produce a generator | Wrap with tuple(...): tuple(x for x in xs) |
SyntaxError near else for | Wrong if-position for filter | Filter: [x for x in xs if c]; transform: [a if c else b for x in xs] |
NameError on comprehension variable outside | Comprehensions have their own scope | Assign result before using |
| Slow / memory blow-up | Built a list when streaming would do | Use () generator or sum(...), any(...) directly |
| Comprehension never finishes | Iterating an infinite source (e.g. itertools.count()) | Add a guard or use itertools.islice |
See Also
Practice this
on practicepython.inShort exercises that run in your browser and tell you what your code actually did, not just whether a test passed.