K2A-D1-6
Python Dicts and Sets
Created 2022-06-08Updated 2026-05-11programming-language-stack / python / language
- Description:
dict(insertion-ordered hash map since 3.7),set/frozenset, set algebra, and thecollectionsmodule,defaultdict,Counter,OrderedDict,ChainMap - My Notion Note ID: K2A-D1-6
- Created: 2022-06-08
- Updated: 2026-05-11
- License: Reuse is very welcome. Please credit Yu Zhang and link back to the original on yuzhang.io
Table of Contents
1. dict
- Hash map, equivalent of C++
std::unordered_map
1.1 Insertion Order Is Guaranteed (3.7+)
- 3.7+: iteration order matches insertion order (language guarantee)
- 3.6: same behavior as CPython implementation detail
- Lookup remains amortized O(1)
d = {"a": 1, "b": 2, "c": 3}
list(d) # ['a', 'b', 'c'] , always
1.2 Construction and Lookup
d = {"a": 1, "b": 2}
d = dict(a=1, b=2)
d = dict([("a", 1), ("b", 2)])
d = {k: 0 for k in "abc"} # dict comprehension
d["a"] # 1
d["z"] # KeyError
d.get("z") # None , no exception
d.get("z", 0) # 0 , default
- Use
d.get()when missing-is-normal - Use
d[k]when missing-is-a-bug
1.3 Useful Methods
d["new"] = 5 # insert or update
del d["a"] # KeyError if missing
d.pop("a", None) # remove with default, no exception
d.popitem() # remove last (k, v), LIFO
d.setdefault("k", []) # get d["k"] or insert []
d.update(other_dict)
d.clear()
"k" in d # membership
1.4 Views: keys, values, items
for k in d: ... # iterates keys by default
for k in d.keys(): ...
for v in d.values(): ...
for k, v in d.items(): ...
- Views are live, reflect later mutations of
d - Set-like:
d.keys() & other.keys()works
1.5 Merging Dicts
merged = a | b # 3.9+: new dict; b's keys win on conflict
a |= b # 3.9+: update in place
merged = {**a, **b} # legacy; same semantics
2. set and frozenset
s = {1, 2, 3} # set literal (note: {} is an empty DICT!)
s = set() # empty set
s = set([1, 1, 2]) # {1, 2}
fs = frozenset([1, 2]) # immutable, hashable
- Set elements must be hashable
frozensetitself is hashable → can be a dict key
2.1 Set Algebra
| Op | Method | Meaning |
|---|---|---|
| |
union |
elements in either |
& |
intersection |
elements in both |
- |
difference |
in left, not in right |
^ |
symmetric_difference |
in exactly one |
<= |
issubset |
every left elt is in right |
>= |
issuperset |
every right elt is in left |
< |
proper subset | subset and not equal |
a = {1, 2, 3}
b = {2, 3, 4}
a | b # {1, 2, 3, 4}
a & b # {2, 3}
a - b # {1}
a ^ b # {1, 4}
a.add(4)
a.discard(99) # no error if absent
a.remove(2) # KeyError if absent
a.update([5, 6])
3. collections
3.1 defaultdict
- Auto-creates missing values with a zero-arg factory, avoids
setdefaultboilerplate
from collections import defaultdict
groups = defaultdict(list)
for name, team in roster:
groups[team].append(name) # no KeyError on first append
freq = defaultdict(int)
for w in words:
freq[w] += 1
3.2 Counter
dictsubclass for counting
from collections import Counter
c = Counter("mississippi")
c # Counter({'i': 4, 's': 4, 'p': 2, 'm': 1})
c.most_common(2) # [('i', 4), ('s', 4)]
c["x"] # 0, missing keys give 0, not KeyError
c1 + c2 # add counts
c1 - c2 # subtract (clamped at zero)
c1 & c2 # min of counts
c1 | c2 # max of counts
3.3 OrderedDict
- Largely legacy since 3.7
- Still useful for
move_to_endor order-sensitive equality (regulardictcompares unordered)
from collections import OrderedDict
od = OrderedDict([("a", 1), ("b", 2)])
od.move_to_end("a") # 'a' becomes the last key
od.move_to_end("a", last=False) # ... or the first
3.4 ChainMap
- View over multiple mappings, searched in order
- Useful for layered config (CLI > env > defaults)
from collections import ChainMap
config = ChainMap(cli_args, env_vars, defaults)
config["timeout"] # first hit wins
- Writes go to the first map; the underlying maps are not modified