🐍 Python - Dictionaries
Dictionaries (dict
) are key-value hash tables. They have much more efficient lookups than lists as long as the data fits in RAM. But regular computers should be able to handle dictionaries with more than ten million items.
Dictionaries are indexed by keyes. Key can be anything hashable (__hash__
) that can be compared (__eq__
), but strings are the most commonly used keys. Hashing is done to keep lookups fast and equality is used to protect against hash collisions.
phonebook = {
'john': 123,
'bob': 456,
}
phonebook['alice'] = 789
assert isinstance(phonebook, dict)
assert phonebook['bob'] == 456
Use dictionary comprehensions.
squares = {number: number * number for number in range(6)}
assert type(squares) == dict
assert squares == {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
d = {0: 'A', 1: 'B', 2: 'C', 3: 'D'}
inverted = {v: k for k, v in d.items()}
assert inverted == {'A': 0, 'B': 1, 'C': 2, 'D': 3}
Dictionary items don't have order. Use ordered dictionaries if order is important in your use-case.
from collections import OrderedDict
od = OrderedDict(one=1, two=2, three=3)
od['four'] = 4
assert od['two'] == 2
Or you can just sort the dictionary when it is read.
import operator
xs = {'a': 2, 'b': 3, 'c': 1}
assert sorted(xs.items()) == [('a', 2), ('b', 3), ('c', 1)]
assert sorted(xs.items(), key=operator.itemgetter(1)) == [('c', 1), ('a', 2), ('b', 3)]
assert sorted(xs.items(), key=lambda x: x[1]) == [('c', 1), ('a', 2), ('b', 3)]
Accessing missing key will raise KeyError
. You can use .get()
, .setdefault()
or defaultdict
to fetch keys safely.
phonebook = {
'john': 123,
'bob': 456,
'alice': 789,
}
# phonebook['matt'] # => KeyError
assert phonebook.get('matt') is None
assert phonebook.get('matt', 0) == 0
from collections import defaultdict
dd_phonebook = defaultdict(lambda: 0)
dd_phonebook.update(phonebook)
assert dd_phonebook['john'] == 123
assert dd_phonebook['matt'] == 0
reservations = {
'table1': [1],
'table2': [2, 3],
}
incoming_reservations = [
('table1', 4),
('table3', 5),
('table4', 6),
]
for ir in incoming_reservations:
reservations.setdefault(ir[0], []).append(ir[1])
assert reservations == {
'table1': [1, 4],
'table2': [2, 3],
'table3': [5],
'table4': [6],
}
Use ChainMap
to search multiple dictionaries.
from collections import ChainMap
canines = {
'grey wolf': 'canis lupus',
'dire wolf': 'canis dirus',
'maned wolf': 'chrysocyon brachyurus',
'red wolf': 'canis rufus',
}
felines = {
'bobcat': 'lynx rufus',
'tiger': 'panthera tigris',
'lion': 'panthera leo',
'leopard': 'panthera pardus',
}
animals = ChainMap(canines, felines)
assert animals['dire wolf'] == 'canis dirus'
assert animals['bobcat'] == 'lynx rufus'
# animals['poodle'] => KeyError
Use dictionaries when you would require a switch statement.
from typing import Optional
def operate(operator, x, y) -> Optional[float]:
return {
'add': lambda: x + y,
'sub': lambda: x - y,
'mul': lambda: x * y,
'div': lambda: x / y,
}.get(operator, lambda: None)()
assert operate('mul', 2, 4) == 8.0
assert operate('mulz', 2, 4) is None
Merging dictionaries is done with update
or **
.
xs = {'a': 1, 'b': 2}
ys = {'b': 3, 'c': 4}
aa = {}
aa.update(xs)
aa.update(ys)
assert aa == {'a': 1, 'b': 3, 'c': 4}
bb = {**xs, **ys}
assert bb == {'a': 1, 'b': 3, 'c': 4}
Source
- Python Tricks The Book, Dan Bader
- Fluent Python, Luciano Ramalho