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
setdoes 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 classic set.
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 userThanks 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! 👀