Matheion

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 empty set; {} builds an empty dict. Empty set literal is set().
  • Fast membership: x in s average 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; raises KeyError if missing—good when absence is a logic bug.
  • d.get(k, default): returns default when k absent—good when absence is ordinary (counts defaulting to 0, etc.).
  • d[k] = v inserts or overwrites.
  • Common bulk views: d.keys(), d.values(), d.items() (each view reflects live dict).

Patterns

  • Invert / group: build list values under keys with .setdefault or collections.defaultdict (later).
  • Frequency counting: loop with .get or increment via Counter (stdlib—optional upgrade).
  • Freeze keys: never mutate an object that is currently acting as a dict key—hashes would change and break structure.

Self-study checklist

  • Draw Venn-style pictures for | & - ^ with small toy sets.
  • Decide case-by-case [] vs .get rule.
  • 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. 1.What is the value of `{1, 2, 3} | {3, 4}`?

  2. 2.Which of these cannot be used as a dictionary **key**?

  3. 3.What is `len({True: 'a', 1: 'b'})`?

  4. 4.You want a count from a dict, defaulting to `0` when the key is missing, without a `KeyError`. Which is best?

  5. 5.What does `set([3, 1, 2, 2, 3, 1])` evaluate to?