Dict & Set Comprehensions
debt(d3/e1/b1/t3)
Closest to 'default linter catches the common case' (d3), ruff and pylint flag unnecessary-comprehension and dict()/list comprehension simplifications automatically.
Closest to 'one-line patch or single-call swap' (e1), per quick_fix — rewriting a loop as a comprehension or swapping list for generator is a localized one-line change.
Closest to 'minimal commitment' (b1), a comprehension is a syntactic pattern at one expression site; choosing it imposes no structural weight on the codebase.
Closest to 'minor surprise' (t3), per misconception — devs wrongly assume comprehensions are always faster, and the generator-vs-list distinction is a documented edge case but rarely catastrophic.
Also Known As
TL;DR
Explanation
Comprehensions: list [expr for x in iterable if cond], dict {k: v for ...}, set {expr for ...}, generator (expr for ...). They are faster than equivalent for-loops (built-in optimisation), more readable for simple transformations, and composable. Nested comprehensions (matrix flattening) are possible but harm readability beyond two levels. Generator expressions are lazy — use when you only iterate once to avoid building the full list. dict.fromkeys() and Counter() are preferable to comprehensions for specific patterns.
Common Misconception
Why It Matters
Common Mistakes
- Nested comprehensions with 3+ levels — break into named generators for readability.
- List comprehension when a generator suffices — [x for x in data] passed to sum() builds a full list; use sum(x for x in data).
- Complex filtering logic in comprehension conditions — extract to a named function.
- Mutating state inside a comprehension — comprehensions are for building new structures, not side effects.
Code Examples
# Verbose for-loop patterns:
name_map = {}
for user in users:
name_map[user.id] = user.name
active_ids = []
for user in users:
if user.is_active:
active_ids.append(user.id)
unique_roles = set()
for user in users:
unique_roles.add(user.role)
# Concise comprehensions:
name_map = {user.id: user.name for user in users}
active_ids = [user.id for user in users if user.is_active]
unique_roles = {user.role for user in users}
# Generator expression (lazy — no full list built):
total = sum(order.total for order in orders if order.is_complete)
# Nested — flatten matrix:
flat = [cell for row in matrix for cell in row]