Dictionaries
Dicts map hashable keys to arbitrary values with average O(1) lookup. They are the default tool for records, indexes, caches, and dispatch tables in Python application code.
Search across all documentation pages
Dicts map hashable keys to arbitrary values with average O(1) lookup. They are the default tool for records, indexes, caches, and dispatch tables in Python application code.
defaults = {"retries": 3, "timeout": 30}
overrides = {"timeout": 60}
config = defaults | overrides
for key in config:
print(key, config[key])
if "retries" not in config:
config["retries"] = 1When to reach for this:
Counter)from collections.abc import Callable
Handler = Callable[[dict], str]
def dispatch(handlers: dict[str, Handler], event: dict) -> str:
kind = str(event.get("type", "unknown"))
handler = handlers.get(kind, handlers["unknown"])
return handler(event)
def merge_records(base: dict[str, object], patch: dict[str, object]) -> dict[str, object]:
merged = base.copy()
merged.update(patch)
return merged
def invert_unique(mapping: dict[str, int]) -> dict[int, str]:
return {value: key for key, value in mapping.items()}
if __name__ == "__main__":
handlers: dict[str, Handler] = {
"user.created": lambda e: f"create {e['id']}",
"unknown": lambda e: "noop",
}
print(dispatch(handlers, {"type": "user.created", "id": 42}))
print(merge_records({"a": 1}, {"b": 2}))What this demonstrates:
handlers.get(kind, default) avoids KeyError for unknown eventsdict.copy + update shallow-merges recordskeys(), values(), items() are dynamic views, not snapshots.dict.fromkeys(keys, default) builds dict with shared default caution.| Syntax | Mutates left? |
|---|---|
a | b | No - new dict (3.9+) |
a.update(b) | Yes |
{**a, **b} | No - new dict |
# setdefault only when missing
counts: dict[str, int] = {}
counts.setdefault("a", 0)
counts["a"] += 1
# pop with default
value = config.pop("missing", None)dict.fromkeys(keys, []) shares one list. Fix: Comprehension with fresh mutable.list(d) snapshot first.__slots__ objects for records.| Alternative | Use When | Don't Use When |
|---|---|---|
TypedDict | Static shape for JSON dicts | Need methods or validation |
dataclass | Structured objects with behavior | Need JSON dict verbatim |
Pydantic model | Validated API models | Inner hot loop |
sqlite | Queryable persistent index | Tiny in-memory map |
Yes - insertion order is guaranteed. Reassigning existing key does not change position in 3.7+ CPython behavior for new insert only.
Immutable types with stable __hash__ - str, int, tuple of hashables. Mutable objects fail.
| returns new merged dict. update mutates in place - pick based on immutability needs.
collections.defaultdict or setdefault - defaultdict cleaner for grouping patterns.
sorted(d.items(), key=lambda kv: kv[1]) returns list of pairs - dict itself stays unordered conceptually but keeps insert order of reassigned dict.
Search stack of dicts without copying - useful for scoped configuration overlays.
copy.deepcopy when nested mutables must be independent.
d[k] raises KeyError when missing. get returns None or default - safer for optional keys.
{k: f(v) for k, v in items} idiomatic for transforms with optional if filter.
When you need columnar analytics (pandas/polars) or relational joins across many rows.
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 16, 2026