All you need to know about frozenset in Python
A frozenset
is an immutable variant of the set
type in Python.
This means that once created, it cannot be modified: it is impossible to add or remove elements from it.
In short: a
frozenset
is a "frozen"set
! Perfect for guaranteeing the integrity of a set of values.
Concretely, we can imagine using a frozenset in these scenarios:
- To protect a dataset against any accidental modification;
- To use a set as a key in a dictionary, which
set
does not allow; - To benefit from a hashable type, useful in advanced contexts.
Differences between set and frozenset
Comparative table
Here are the main differences between a set
and a frozenset
:
Characteristic | set | frozenset |
Modifiable? | ✅ Yes | ❌ No |
Hashable? | ❌ No | ✅ Yes |
Can be a dictionary key? | ❌ No | ✅ Yes |
Addition / removal? | ✅ Yes (add, remove, pop, etc) | ❌ No |
Comparative example
From a code perspective, here's what it looks like:
# Set
s = {1, 2, 3}
s.add(4) # ✅ OK
# Frozenset
fs = frozenset([1, 2, 3])
fs.add(4) # ❌ Error: 'frozenset' object has no attribute 'add'
Using frozenset
effectively prevents involuntary modifications to the dataset, especially in complex projects where multiple functions share the same object. 😉
Creating a frozenset
The keyword to create an immutable set is simply: frozenset()
. Easy! 🥸
# From a list
fs1 = frozenset([1, 2, 3])
# From a set
s = {4, 5}
fs2 = frozenset(s)
# From a string
fs3 = frozenset("abc") # {'a', 'b', 'c'}
A
frozenset
also eliminates duplicates, like a classicset
.PYTHONfs = frozenset([1, 2, 2, 3]) print(fs) # frozenset({1, 2, 3})
Operations on a frozenset
Even though a frozenset
is immutable, it accepts all classic set operations.
Union (with "|")
A union allows you to combine all elements from a frozenset A
and a second frozenset B
.
a = frozenset([1, 2])
b = frozenset([2, 3])
print(a | b) # frozenset({1, 2, 3})
Note that the "2" was removed because it was duplicated: we only kept one, thanks to the uniqueness property of sets (therefore frozensets).
Intersection (with "&")
An intersection allows you to retrieve only the elements that are both in frozenset A
and in frozenset B
.
a = frozenset([1, 2])
b = frozenset([2, 3])
print(a & b) # frozenset({2})
Difference (with "-")
A difference gives the elements that are in frozenset A
and not in frozenset B
.
a = frozenset([1, 2])
b = frozenset([2, 3])
print(a - b) # frozenset({1})
Symmetric difference (with "^")
A symmetric difference gives the elements in frozenset A
that are not in frozenset B
and vice versa (unlike a simple difference).
a = frozenset([1, 2])
b = frozenset([2, 3])
print(a ^ b) # frozenset({1, 3})
Frozenset as a dictionary key
One of the main reasons to use a frozenset
is that it is hashable, which allows it to be used as a key in a dictionary (impossible with a classic set
).
permissions = {
frozenset(['read', 'write']): 'Standard user',
frozenset(['read', 'write', 'delete']): 'Administrator'
}
print(permissions[frozenset(['read', 'write'])]) # Standard user
Thanks to this property, frozenset
becomes very useful in cases where you want to associate sets of permissions, tags, or properties to a specific value.
Use in sets of sets
Since a set
can only contain hashable objects, it cannot contain another set
. However, it can perfectly contain a frozenset
.
a = frozenset([1, 2])
b = frozenset([2, 3])
set_of_sets = {a, b}
print(set_of_sets)
All this opens the door to advanced use cases:
- Comparison of data clusters (clustering);
- Analysis of graphs or networks;
- Validation of immutable configurations.
If you need a set of sets,
frozenset
is your only ally in native Python.
Typing with frozenset
Python provides a specific type annotation for frozenset
via the typing
module.
from typing import FrozenSet
def process_permissions(permissions: FrozenSet[str]) -> None:
print("Permissions received:", permissions)
This typing allows you to better document your code while making it compatible with static checking tools like mypy
or pyright
.
Comparison between frozenset and tuple
Another comparison quite often made with frozenset
is with tuple
.
Criterion | frozenset | tuple |
Ordered? | ❌ No | ✅ Yes |
Duplicates allowed? | ❌ No | ✅ Yes |
Index access? | ❌ No | ✅ Yes |
Set operations? | ✅ Yes | ❌ No |
Generally speaking, tuple
is more suitable for positional data, while frozenset
is ideal for sets of unique properties.
Frequently asked questions about frozenset
Can you sort a
frozenset
?
No, but you can convert it:
sorted_list = sorted(frozenset([3, 1, 2])) # [1, 2, 3]
Why not always use
frozenset
?
Because it is less flexible. If you need to modify the set, prefer set
.
How to learn Python?
With an awesome Python course! 👀