reference
5 min read
·
lesson 4 of 16 in Reference
Python Dictionary Cheat Sheet
1 · The lesson
readMutable 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
| Expression | Behaviour |
|---|---|
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 d | Membership (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
| Method | Behaviour |
|---|---|
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')
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
| Error | Cause | Fix |
|---|---|---|
KeyError: 'foo' | d[k] when k missing | Use .get(k) or .get(k, default) or check if k in d |
RuntimeError: dictionary changed size during iteration | Adding/removing keys inside for k in d: | Iterate over list(d) or build a new dict |
TypeError: unhashable type: 'list' | List used as key | Use a tuple instead: d[(1, 2)] = ... |
TypeError: 'dict_keys' object is not subscriptable | d.keys()[0] | Wrap: list(d.keys())[0] or use next(iter(d)) |
| Values overwritten on merge | a | b — b wins | Reverse: b | a for a-wins |
See Also
Practice this
on practicepython.inShort exercises that run in your browser and tell you what your code actually did, not just whether a test passed.