PythonMastery
reference 5 min read · lesson 8 of 16 in Reference

Python Comprehensions Cheat Sheet

1 · The lesson

read

Quick reference for list, set, dict, and generator comprehensions. For the full tutorial see Comprehensions.

1. The Four Comprehension Forms

FormSyntaxResult typeExample 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:

PositionFormEffect
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 / SymptomCauseFix
(1, 2, 3) expected but got generator objectParens around comprehension produce a generatorWrap with tuple(...): tuple(x for x in xs)
SyntaxError near else forWrong if-position for filterFilter: [x for x in xs if c]; transform: [a if c else b for x in xs]
NameError on comprehension variable outsideComprehensions have their own scopeAssign result before using
Slow / memory blow-upBuilt a list when streaming would doUse () generator or sum(...), any(...) directly
Comprehension never finishesIterating an infinite source (e.g. itertools.count())Add a guard or use itertools.islice

See Also

Practice this

on practicepython.in

Short exercises that run in your browser and tell you what your code actually did, not just whether a test passed.