PythonMastery
reference 5 min read · lesson 4 of 16 in Reference

Python Dictionary Cheat Sheet

1 · The lesson

read

Mutable mapping of hashable keys to values. Insertion-ordered (3.7+). Average O(1) lookup. For the full tutorial, see Dictionaries.


Creating

python
a = {"name": "Ada", "age": 36}
b = dict()                              # {}
c = dict(name="Ada", age=36)            # kwargs (str keys only)
d = dict([("a", 1), ("b", 2)])          # from pairs
e = dict(zip(["a","b","c"], [1,2,3]))   # zip two lists
f = dict.fromkeys(["a","b","c"], 0)     # {'a':0,'b':0,'c':0}
g = {k: v for k, v in pairs}            # comprehension
+ setup added so this can run · defines pairs
pairs = [("alpha", 1), ("beta", 2), ("gamma", 3)]

Accessing

ExpressionBehaviour
d[k]Value or KeyError
d.get(k)Value or None
d.get(k, default)Value or default (does not insert)
d.setdefault(k, default)Value or insert default then return it
k in dMembership (checks keys)
python
d = {"a": 1}
d["a"]                  # 1
d["z"]                  # KeyError
d.get("z")              # None
d.get("z", 0)           # 0
d.setdefault("z", [])   # [] (and now d['z'] = [])
d.setdefault("z", [99]) # [] (already exists, no overwrite)

Adding & Updating

python
d["new"] = 42                       # set or overwrite
d.update({"a": 10, "b": 20})        # merge dict in place
d.update(c=30, d=40)                # via kwargs
d.update([("e", 50)])               # from pairs

# Merge operators (3.9+)
merged = a | b                      # new dict, b wins on conflict
a |= b                              # in place
+ setup added so this can run · defines a, b, d
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

a = _AutoMock('a')
b = _AutoMock('b')
d = _AutoMock('d')

Removing

MethodBehaviour
del d[k]Remove, raises KeyError if missing
d.pop(k)Remove & return value, raises KeyError
d.pop(k, default)Remove & return value, or default
d.popitem()Remove & return last (k, v) pair
d.clear()Empty the dict
python
d = {"a": 1, "b": 2}
d.pop("a")              # 1, d = {'b': 2}
d.pop("z", None)        # None (safe)
d.popitem()             # ('b', 2)

Iterating

python
d = {"a": 1, "b": 2}

for k in d:              ...        # keys (default)
for k in d.keys():       ...        # same
for v in d.values():     ...
for k, v in d.items():   ...

list(d)                  # ['a', 'b']
list(d.values())         # [1, 2]
list(d.items())          # [('a', 1), ('b', 2)]

.keys(), .values(), .items() return views — live, lightweight, iterable.

Membership

python
"a" in d            # True (checks keys)
"a" not in d        # False
1 in d.values()     # True (O(n))
+ setup added so this can run · defines d
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

d = _AutoMock('d')

Merging

python
# 3.9+ pipe operators
combined = a | b
a |= b

# Pre-3.9 patterns
combined = {**a, **b}           # unpack — b wins on conflict
combined = dict(a, **b)         # b's keys must be strings

a.update(b)                     # in place, b wins
+ setup added so this can run · defines a, b
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

a = _AutoMock('a')
b = _AutoMock('b')

Sorting

python
d = {"banana": 3, "apple": 1, "cherry": 2}

# By keys
dict(sorted(d.items()))
# {'apple': 1, 'banana': 3, 'cherry': 2}

# By values
dict(sorted(d.items(), key=lambda kv: kv[1]))
# {'apple': 1, 'cherry': 2, 'banana': 3}

# Descending by value, tie-break by key
sorted(d.items(), key=lambda kv: (-kv[1], kv[0]))

# Top-3 by value
sorted(d.items(), key=lambda kv: -kv[1])[:3]

Comprehensions

python
{k: v * 2 for k, v in d.items()}
{k: v for k, v in d.items() if v > 0}
{v: k for k, v in d.items()}                # invert
{x: x**2 for x in range(5)}
+ setup added so this can run · defines d
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

d = _AutoMock('d')

Counter & defaultdict

python
from collections import Counter, defaultdict

Counter("mississippi")
# Counter({'i': 4, 's': 4, 'p': 2, 'm': 1})
Counter(words).most_common(3)
Counter("aab") + Counter("abc")             # Counter({'a':3,'b':2,'c':1})

dd = defaultdict(list)
dd["x"].append(1)                           # auto-creates []
dd = defaultdict(int)
dd["count"] += 1                            # auto-zero
+ setup added so this can run · defines words
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

words = _AutoMock('words')

See Collections Cheat Sheet.

Common Patterns

python
# Group by
groups = {}
for item in items:
    groups.setdefault(item.cat, []).append(item)

# Same with defaultdict
from collections import defaultdict
groups = defaultdict(list)
for item in items:
    groups[item.cat].append(item)

# Count occurrences
counts = {}
for x in xs:
    counts[x] = counts.get(x, 0) + 1
# Or: counts = Counter(xs)

# Invert (assumes unique values)
inv = {v: k for k, v in d.items()}

# Filter
{k: v for k, v in d.items() if v is not None}

# Pick subset of keys
{k: d[k] for k in ("name", "age") if k in d}
+ setup added so this can run · defines items, xs, d
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

items = ["alpha", "beta", "gamma"]
xs = ["alpha", "beta", "gamma"]
d = _AutoMock('d')

Common Errors

ErrorCauseFix
KeyError: 'foo'd[k] when k missingUse .get(k) or .get(k, default) or check if k in d
RuntimeError: dictionary changed size during iterationAdding/removing keys inside for k in d:Iterate over list(d) or build a new dict
TypeError: unhashable type: 'list'List used as keyUse a tuple instead: d[(1, 2)] = ...
TypeError: 'dict_keys' object is not subscriptabled.keys()[0]Wrap: list(d.keys())[0] or use next(iter(d))
Values overwritten on mergea | b — b winsReverse: b | a for a-wins

See Also

Practice this

on practicepython.in

Short exercises that run in your browser and tell you what your code actually did, not just whether a test passed.