Python Dict Comprehension Cheat Sheet
Dict comprehensions build mappings without explicit loops, the same way list comprehensions build lists. They are the right tool for inverting a dict, projecting a list of tuples into a key-value map, and filtering an existing dict by predicate. This snippet covers the basic build form, the invert and merge patterns, and the filtering form for trimming an existing dict.
1,133 views
15
names = ['Ada', 'Bo', 'Cal']
lengths = {name: len(name) for name in names}
print(lengths) # {'Ada': 3, 'Bo': 2, 'Cal': 3}
squares = {n: n * n for n in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
rows = [('a', 1), ('b', 2), ('c', 3)]
from_pairs = {k: v for k, v in rows}
print(from_pairs) # {'a': 1, 'b': 2, 'c': 3}Dict comprehensions use {key: value for ... in iterable}. The most common shape is computing a key from each element and a value from a function of that element, which collapses a five-line for / dict[key] = value loop into one expression. Building from a list of tuples is identical to dict(rows), but the comprehension form is more flexible because it lets you transform the keys and values inline. Time complexity is O(n) for n input elements.
user_id_by_email = {'[email protected]': 1, '[email protected]': 2, '[email protected]': 3}
email_by_user_id = {v: k for k, v in user_id_by_email.items()}
print(email_by_user_id) # {1: '[email protected]', 2: '[email protected]', 3: '[email protected]'}
defaults = {'theme': 'light', 'lang': 'en'}
user = {'lang': 'fr', 'name': 'Cal'}
merged = {**defaults, **user}
print(merged) # {'theme': 'light', 'lang': 'fr', 'name': 'Cal'}
renamed = {f'user_{k}': v for k, v in user.items()}
print(renamed) # {'user_lang': 'fr', 'user_name': 'Cal'}Inverting a dict (swapping keys and values) is a one-liner with {v: k for k, v in d.items()}. This only works when the values are hashable AND unique; duplicate values silently lose data because later writes win. Merging two dicts with {**a, **b} is the modern syntax (Python 3.5+) for b overriding a, useful for layered configs. Renaming keys with an f-string in the comprehension is the canonical way to add a prefix without writing a new function.
scores = {'ada': 95, 'bo': 62, 'cal': 88, 'di': 41}
passing = {name: score for name, score in scores.items() if score >= 70}
print(passing) # {'ada': 95, 'cal': 88}
normalized = {name.title(): score / 100 for name, score in scores.items()}
print(normalized) # {'Ada': 0.95, 'Bo': 0.62, 'Cal': 0.88, 'Di': 0.41}
grouped = {name: ('high' if s >= 80 else 'mid' if s >= 60 else 'low') for name, s in scores.items()}
print(grouped) # {'ada': 'high', 'bo': 'mid', 'cal': 'high', 'di': 'low'}An if clause inside the dict comprehension filters which key-value pairs survive, the same way it does for list comprehensions. Combining filtering with transformation produces concise code for common operations like 'keep only passing scores', 'normalise to floats', 'bucket into bands'. Watch out for the same readability ceiling: comprehensions with two transformations and a filter can be fine, but an f-string key plus a chained ternary value plus a filter is usually a sign that a regular for loop or a helper function would read better.
