MA-PY1 · Module 2.3
Sets and dictionaries
Topics: Sets · Dictionaries · Hashing concepts
Overview
Module 2.3 — Sets and dictionaries
Scroll Core ideas → worked snippets → Practice (quiz). Attempt each question before Discuss / reveal. Use any Python REPL, script, or notebook you like.
Concepts
Core ideas — sets and dictionaries
When you only care about membership or unique values, a set is the right mental model. When you need associative memory (“map this key to that value”), a dict is the workhorse.
First, what does hashable mean?
Both sets and dictionaries lean on one idea you will see repeatedly: hashable. A value is hashable when Python can compute a small, fixed fingerprint number (its hash) that never changes for the life of the value. That fingerprint is how a set or dict finds things almost instantly instead of scanning every entry.
The practical rule is simple: immutable values are hashable, mutable ones are not. Numbers, strings, and tuples (of immutable things) are hashable, so they can go into a set or be used as dictionary keys. A list can be changed in place, so its fingerprint would drift — Python refuses to hash it, which is why {[]: 1} raises a TypeError. If you ever need a list-like key, freeze it into a tuple first: tuple(my_list).
Keep this one sentence in mind for the rest of the module: set elements and dict keys must be hashable (think "immutable").
Sets
- Unordered collection of distinct hashable items (ints, strings, tuples of immutables—not lists as elements).
- Literal syntax:
{1, 2, 3}— do not confuse{}with an emptyset;{}builds an empty dict. Empty set literal isset(). - Fast membership:
x in saverage O(1). - Operations:
|union,&intersection,-difference,^symmetric difference.
set.add mutates; union returns new unless you use |= variants.
Dictionaries
- Keys must be hashable; values can be anything—including lists, other dicts,
None. - Insertion order preserved since Python 3.7 (CPython guarantee). That’s not “sorted order”—just stable round-trip when you iterate
for k in d:. d[k]: fast lookup; raisesKeyErrorif missing—good when absence is a logic bug.d.get(k, default): returnsdefaultwhenkabsent—good when absence is ordinary (counts defaulting to0, etc.).d[k] = vinserts or overwrites.- Common bulk views:
d.keys(),d.values(),d.items()(each view reflects live dict).
Patterns
- Invert / group: build
listvalues under keys with.setdefaultorcollections.defaultdict(later). - Frequency counting: loop with
.getor increment viaCounter(stdlib—optional upgrade). - Freeze keys: never mutate an object that is currently acting as a
dictkey—hashes would change and break structure.
Self-study checklist
- Draw Venn-style pictures for
| & - ^with small toy sets. - Decide case-by-case
[]vs.getrule. - Explain why
{[]: 1}errors.
Examples
Worked snippets — sets & dicts
Uniquify and test membership
tags = {"cpu", "io", "dma", "cpu"}
print(tags, "cpu" in tags)
Set algebra
a = {1, 2, 3}
b = {2, 3, 4}
print(a | b) # union
print(a & b) # intersection
print(a - b) # in a not b
print(a ^ b) # symmetric diff
Build a frequency table manually
words = ["to", "be", "or", "not", "to", "be"]
counts = {}
for w in words:
counts[w] = counts.get(w, 0) + 1
print(counts)
Equivalent pattern with setdefault:
counts = {}
for w in words:
counts.setdefault(w, 0)
counts[w] += 1
Iteration order is insertion order
order = {}
order["third"] = 3
order["first"] = 1
print(list(order.items()))
Keys appear in insertion order; use sorted(order) when you need alphabetical or numeric key order for display.
.items() unpacking
scores = {"ada": 100, "lin": 95}
for name, pts in scores.items():
print(f"{name}: {pts}")
Guarded vs strict lookup
prefs = {"theme": "dark"}
print(prefs.get("fontsize", 12)) # default when absent
print(prefs["theme"]) # raises KeyError if key missing — use only when BUG if absent
# Uncomment to observe KeyError in REPL experiments:
# print(prefs["missing"])
Practice check — sets and dictionaries
Multiple-choice check from the Matheion app lesson. Pick an answer for each question, then submit.
1.What is the value of `{1, 2, 3} | {3, 4}`?
2.Which of these cannot be used as a dictionary **key**?
3.What is `len({True: 'a', 1: 'b'})`?
4.You want a count from a dict, defaulting to `0` when the key is missing, without a `KeyError`. Which is best?
5.What does `set([3, 1, 2, 2, 3, 1])` evaluate to?