Lesson 11
Frozenset — Immutable Sets and Read-Only Algebra
Create immutable sets, perform read-only set algebra, and understand when frozenset is required for dictionary keys and nested sets.
What you will learn
Create frozensets · Read-only set methods · Hashable collections · Cache and permission patterns
Create immutable sets, perform read-only set algebra, and understand when frozenset is required for dictionary keys and nested sets.
| Topic | Why it matters |
|---|---|
| Creation | Build from any iterable |
| Read-only algebra | Compare groups without mutation |
| Hashability | Use as dict keys and nested set members |
| Real patterns | Permission caches and memoization |
Think of
frozensetas the read-only version ofset.
After File 10 — Set Algebra, you know union, intersection, difference, and symmetric difference on mutable sets. This lesson applies the same algebra to immutable sets — and explains when you must use them.
Learning roadmap
Concept diagram
1. set vs frozenset
A frozenset stores unique elements exactly like a normal set, but once created it cannot be modified.
| Feature | set |
frozenset |
|---|---|---|
| Mutability | Mutable | Immutable |
| Duplicates | Removed automatically | Removed automatically |
| Hashable | No | Yes (if elements are hashable) |
| Set algebra | Yes | Yes (read-only — returns new sets) |
add / remove |
Yes | No |
Deep dive on the type itself: frozenset data type.
2. Creating frozensets
Use the built-in constructor with any iterable.
fs1 = frozenset() # empty
fs2 = frozenset([10, 20, 10, 30]) # list
fs3 = frozenset({1, 2, 3}) # set
fs4 = frozenset("PYTHON") # string
fs5 = frozenset(range(5)) # range
print(fs2)
# frozenset({10, 20, 30})Input → output
| Input | Result |
|---|---|
frozenset([1, 2, 2, 3]) |
frozenset({1, 2, 3}) |
frozenset("MISS") |
frozenset({'M', 'I', 'S'}) |
frozenset((5, 6)) |
frozenset({5, 6}) |
Also works with bytes, bytearray, and any other iterable of hashable elements.
3. Read-only set algebra
Even though you cannot modify a frozenset, you can still perform mathematical set operations. Each operation returns a new set (or frozenset).
| Operation | Syntax | Meaning |
|---|---|---|
| Union | ` | orunion()` |
| Intersection | & or intersection() |
Shared elements only |
| Difference | - or difference() |
Only left-side elements |
| Symmetric | ^ or symmetric_difference() |
Exclusive elements |
a = frozenset({1, 2, 3})
b = frozenset({3, 4, 5})
print(a | b) # frozenset({1, 2, 3, 4, 5})
print(a & b) # frozenset({3})
print(a - b) # frozenset({1, 2})
print(a ^ b) # frozenset({1, 2, 4, 5})Allowed read-only methods
These eight methods work on frozenset (same as read-only algebra on set):
copy, union, intersection, difference, symmetric_difference, isdisjoint, issubset, issuperset
a = frozenset({1, 2, 3})
b = frozenset({3, 4, 5})
print(a.isdisjoint({6, 7})) # True
print(b.issubset(a | b)) # True4. What you cannot do
These methods exist on set but not on frozenset.
| Blocked | Blocked |
|---|---|
add() |
remove() |
discard() |
pop() |
update() |
clear() |
Also blocked: difference_update(), intersection_update(), symmetric_difference_update().
fs = frozenset({1, 2})
fs.add(3)
# AttributeError:
# 'frozenset' object has no attribute 'add'Why? Changing even one element would break the guarantee of immutability.
Need to mutate? Convert to a regular set, change it, then wrap again if needed:
fs = frozenset({1, 2})
s = set(fs)
s.add(3)
fs = frozenset(s)5. Why is frozenset hashable?
A mutable object can change after it is stored, making it unsafe as a dictionary key. Since frozenset never changes, Python allows it to be hashed.
permissions = frozenset({"read", "write"})
cache = {
permissions: "Editor Role"
}
print(cache[permissions]) # Editor RoleThis pattern is common in caching, permission systems, and memoization.
# This fails — set is unhashable
# bad = {{1, 2}: "value"} # TypeError6. Nested sets
A normal set cannot contain another set, because sets are mutable and unhashable.
| Case | Example | Result |
|---|---|---|
| Invalid | { {1, 2} } |
TypeError |
| Valid | { frozenset({1, 2}) } |
Works — immutable and hashable |
groups = {
frozenset({"A", "B"}),
frozenset({"C", "D"})
}
print(groups)
# {frozenset({'A', 'B'}), frozenset({'C', 'D'})}Mini project — permission cache
Imagine an API where users with the same permissions share cached responses.
# Immutable permission bundle
read_only = frozenset({"read", "list"})
cache = {
read_only: "public-api-v1"
}
user_permissions = frozenset({"read", "list"})
print(cache[user_permissions])Output:
public-api-v1Although user_permissions is a different variable, it represents the same immutable set, so it works as the dictionary key.
One-page revision sheet
Interview takeaway:
frozensetis tosetwhattupleis tolist— an immutable version designed for safe hashing and read-only data.
| Task | Syntax |
|---|---|
| Create empty | frozenset() |
| From list | frozenset([1, 2, 3]) |
| Union | `a |
| Intersection | a & b |
| Difference | a - b |
| Symmetric difference | a ^ b |
| Dictionary key | frozenset only |
| Mutable? | No |
Common interview mistakes
Mistake 1 — using set as a dict key:
# TypeError: unhashable type: 'set'
# cache = {{"read"}: "value"}
cache = {frozenset({"read"}): "value"} # correctMistake 2 — expecting union() to mutate:
a = frozenset({1, 2})
a.union({3}) # returns NEW frozenset — does not change aMistake 3 — nesting a mutable set:
# TypeError
# groups = {{1, 2}, {3, 4}}
groups = {frozenset({1, 2}), frozenset({3, 4})}Practice questions
Test yourself before File 12 — Dictionary Methods:
- Which collection can be used as a dictionary key —
setorfrozenset? - What happens when you call
fs.add(10)on a frozenset? - Can a
setcontain anothersetas an element? - Name two real-world uses for
frozenset. - Which operator finds elements in exactly one of two frozensets?
Knowledge check
Q1: Which collection can be used as a dictionary key?
Answer: frozenset (not set, not list).
Q2: What happens here — fs.add(10)?
Answer: AttributeError — frozenset has no add method.
Q3: Can {[1, 2]} be a valid set?
Answer: No — lists are unhashable. {frozenset({1, 2})} works.
Q4: Main reason to pick frozenset over set?
Answer: When you need a hashable, immutable set (dict keys, nested in sets, cache keys).
Q5: Operator for exclusive elements?
Answer: ^ (symmetric difference).
Loading playground…