Dictionaries
Key-value mappings, the most-used data structure in Python
A dict maps keys to values. Lookups, insertions, and deletions are all average-case O(1). Dictionaries are everywhere in Python: JSON decoding produces dicts, function **kwargs are dicts, object __dict__ attributes are dicts, module globals live in a dict, configuration files parse to dicts. Dictionaries are Python. Understanding them deeply is not optional.
Every snippet on this page runs in your browser — no setup required.
How dictionaries work
Under the hood, a dict is a hash table: Python computes a hash of your key, uses that to find a bucket, and stores the key-value pair there. Hash collisions are handled with open addressing. This gives O(1) average-case access.
Dicts are Python's superpower
Python's dict implementation is one of the fastest in any dynamic language. The entire language runtime is built on dicts: every module's namespace, every object's attributes, every function's keyword arguments. When you write obj.attr, Python is doing obj.__dict__['attr'] behind the scenes. Dicts are the engine of Python.
Creating dicts
The simplest dict is written with curly braces, separating key: value pairs with commas.
The dict() constructor accepts keyword arguments or an iterable of (key, value) pairs.
Accessing values
Use [] to access a value by key.
Missing keys raise a KeyError.
.get returns None (or a default you provide) instead of raising.
get vs []
Use d[key] when the key must exist (and you want to crash if it doesn't). Use d.get(key, default) when the key might be missing and you have a sensible fallback. Both are idiomatic; pick the one that matches your intent.
Updating
Assign through [] to add or overwrite a key.
.update merges in another dict or iterable of pairs.
Delete a key with del or .pop.
Iterating
By default, iteration yields keys.
.items() gives (key, value) pairs.
.values() gives just the values.
Insertion order is preserved
Since Python 3.7, dicts officially preserve insertion order. The first item you put in is the first one you see when iterating. Before 3.7, dict order was undefined (though CPython 3.6 had ordered dicts as an implementation detail). This change was a huge quality-of-life improvement.
Keys must be hashable
Keys can be any hashable type: strings, numbers, booleans, tuples-of-hashables, frozensets. Lists, sets, and dicts are mutable and therefore not hashable.
The requirement is hashability, not immutability. A custom class can be mutable yet hashable if it defines __hash__ and __eq__ (though that is rarely a good idea). Conversely, not all immutable types are hashable (e.g., tuple containing a list is immutable but not hashable).
Merging dicts (Python 3.9+)
The | operator creates a new dict; the right operand wins on conflicts.
|= mutates in place.
Before Python 3.9, use .update() or {**a, **b}.
Counting and grouping
collections.Counter and collections.defaultdict cover two of the most common dict patterns.
JSON interop
Dicts and JSON objects share syntax for a reason. The json module converts both ways.
Every web API you call returns JSON, which Python decodes into dicts and lists. Every config file format (JSON, YAML, TOML) parses to nested dicts. Learning dicts is learning how to work with structured data in Python.
Challenges
Define a function word_freq(sentence) that returns a dict mapping each lowercase word in sentence to its frequency. Split on whitespace and treat words case-insensitively. For example, word_freq("To be or not to be") returns {"to": 2, "be": 2, "or": 1, "not": 1}.
Define invert(d) that swaps keys and values of d. You may assume all values are unique and hashable. For example, invert({"a": 1, "b": 2}) returns {1: "a", 2: "b"}.
Define a function merge_sum(d1, d2) that returns a new dict containing all keys from d1 and d2. For keys that appear in both, sum the values. For example:
merge_sum({"a": 1, "b": 2}, {"b": 3, "c": 4})
# returns {"a": 1, "b": 5, "c": 4}
Assume all values are numbers.
Which of these can be used as dictionary keys?
"hello"
[1, 2, 3]
(1, 2, 3)
{"a": 1}
What does the following code print?
d = {"a": 1, "b": 2}
d.setdefault("a", 99)
d.setdefault("c", 3)
print(d)
{"a": 99, "b": 2, "c": 3}
{"a": 1, "b": 2, "c": 3}
{"a": 1, "b": 2}
A KeyError
What is the time complexity of key in d where d is a dict?
O(1) average case
O(n)
O(log n)
O(n²)
Since Python 3.7, what is guaranteed about dict iteration order?
It is undefined and can change between runs.
Sorted by key alphabetically.
Insertion order is preserved.
Sorted by value.
Next up: sets, the close cousin of dictionaries.