Technology  /  Python

🐍 Python 78 guides · updated 2026

From first variable to OOP, generators, and real projects — the language that runs everything from data pipelines to AI agents, taught the practical way.

Python Dictionary Comprehensions: Build Dicts in One Line Without Sacrificing Clarity

Dictionary comprehensions let you construct dictionaries from any iterable in a single expression. Like list comprehensions, they’re faster to write and often faster to read than the equivalent loop — provided you keep the logic simple.


Basic Syntax

{key_expression: value_expression for item in iterable}

The key difference from a list comprehension: you provide two expressions separated by a colon, which become the key and value of each entry in the new dict.


Building a Dictionary from a List

The most common case: take a list and create a dictionary mapping each element to something derived from it.

# Map words to their lengths
words = ["Python", "is", "readable", "and", "fast"]
lengths = {word: len(word) for word in words}
print(lengths)
# {'Python': 6, 'is': 2, 'readable': 8, 'and': 3, 'fast': 4}
# Map numbers to their squares
numbers = range(1, 6)
squares = {n: n**2 for n in numbers}
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

The loop equivalent for context:

squares = {}
for n in range(1, 6):
squares[n] = n**2

Building from Two Lists

zip() pairs up two lists element by element, which maps directly to key-value pairs:

countries = ["Germany", "Japan", "Brazil"]
capitals = ["Berlin", "Tokyo", "Brasília"]
capital_of = {country: capital for country, capital in zip(countries, capitals)}
print(capital_of)
# {'Germany': 'Berlin', 'Japan': 'Tokyo', 'Brazil': 'Brasília'}

This is a clean replacement for dict(zip(countries, capitals)) when you want to transform the keys or values before storing them.


Filtering with Conditions

Add an if clause at the end to skip items that don’t meet a condition:

scores = {"Alice": 92, "Bob": 61, "Charlie": 78, "Diana": 45, "Eve": 88}
# Keep only passing scores
passing = {name: score for name, score in scores.items() if score >= 70}
print(passing)
# {'Alice': 92, 'Charlie': 78, 'Eve': 88}
# Filter a product list by availability
products = {
"Widget": {"price": 9.99, "stock": 5},
"Gadget": {"price": 24.99, "stock": 0},
"Doohickey": {"price": 4.99, "stock": 12},
}
available = {name: info for name, info in products.items() if info["stock"] > 0}

Transforming Keys and Values

Comprehensions let you modify both the keys and values as you build the new dict:

# Uppercase all keys
config = {"debug": True, "host": "localhost", "port": 8080}
upper_config = {k.upper(): v for k, v in config.items()}
# {'DEBUG': True, 'HOST': 'localhost', 'PORT': 8080}
# Apply a function to all values
prices = {"apple": 1.20, "banana": 0.50, "cherry": 3.00}
discounted = {item: round(price * 0.9, 2) for item, price in prices.items()}
# {'apple': 1.08, 'banana': 0.45, 'cherry': 2.7}

Inverting a Dictionary

When values are unique, you can swap keys and values:

abbreviations = {"US": "United States", "UK": "United Kingdom", "AU": "Australia"}
full_name_to_code = {full: code for code, full in abbreviations.items()}
# {'United States': 'US', 'United Kingdom': 'UK', 'Australia': 'AU'}

This only works reliably when values are unique. If multiple keys share a value, only the last one survives in the inverted dict.


Conditional Expressions in Values

You can use a ternary expression in the value part:

raw_data = {"temperature": "22.5", "pressure": None, "humidity": "65"}
# Convert numeric strings, keep None as None
processed = {
k: float(v) if v is not None else None
for k, v in raw_data.items()
}
# {'temperature': 22.5, 'pressure': None, 'humidity': 65.0}

Nested Dict Comprehensions

Comprehensions can produce nested dictionaries, though readability degrades quickly with depth:

# Build a multiplication table as a nested dict
table = {i: {j: i * j for j in range(1, 6)} for i in range(1, 6)}
print(table[3][4]) # 12
# Accessible, but getting hard to read

For anything beyond one level of nesting, consider using a regular loop:

table = {}
for i in range(1, 6):
table[i] = {j: i * j for j in range(1, 6)}

The inner comprehension is still clear; the outer loop makes the structure explicit.


Grouping Data

One common pattern is grouping a list of records by some attribute:

employees = [
{"name": "Alice", "dept": "Engineering"},
{"name": "Bob", "dept": "Marketing"},
{"name": "Charlie", "dept": "Engineering"},
{"name": "Diana", "dept": "Marketing"},
]
# Dict comprehension doesn't directly support grouping — use defaultdict instead
from collections import defaultdict
by_dept = defaultdict(list)
for emp in employees:
by_dept[emp["dept"]].append(emp["name"])
# {'Engineering': ['Alice', 'Charlie'], 'Marketing': ['Bob', 'Diana']}

A dict comprehension isn’t the right tool for grouping (you’d lose all but the last record per key). Use defaultdict or itertools.groupby for that.


When Not to Use a Dict Comprehension

When the logic is complex. If you need multiple conditions, nested logic, or intermediate variables, a loop is clearer:

# Too dense — hard to review or debug
result = {k: transform(v) for k, v in data.items() if complex_check(k) and v is not None}
# Better as a loop
result = {}
for k, v in data.items():
if v is None:
continue
if not complex_check(k):
continue
result[k] = transform(v)

When you need to handle errors per-key. You can’t put a try/except inside a comprehension. Use a loop.

When grouping or accumulating. A comprehension produces one value per key, not a list per key. Use defaultdict for multi-value grouping.

The best dict comprehensions are short and tell you their purpose at a glance. If you find yourself explaining the comprehension to make it understandable, it’s time to expand it into a loop.