Of course! Let's dive deep into Python's frozenset().

What is a frozenset()?
A frozenset() is an immutable, unordered collection of unique elements.
Let's break that down:
- Set: Like a regular
set, it stores unique elements. This means no duplicates are allowed. - Unordered: The elements are not stored in any specific order (like a list or tuple). You can't access elements by index (e.g.,
my_frozenset[0]). - Immutable: This is the key difference from a regular
set. Once you create afrozenset, you cannot change it. You can't add new elements, remove existing ones, or modify any elements in it.
Think of it as a tuple versus a list. A tuple is an immutable list, and a frozenset is an immutable set.
How to Create a frozenset()
You create a frozenset using the frozenset() constructor. It can take any iterable (like a list, tuple, or a string) as an argument.

# From a list
my_list = [1, 2, 2, 3, 4, 4, 5]
fset_from_list = frozenset(my_list)
print(f"From list: {fset_from_list}") # Output: From list: frozenset({1, 2, 3, 4, 5})
# From a tuple
my_tuple = ('a', 'b', 'c', 'a')
fset_from_tuple = frozenset(my_tuple)
print(f"From tuple: {fset_from_tuple}") # Output: From tuple: frozenset({'c', 'a', 'b'})
# From a string (each character becomes an element)
my_string = "hello"
fset_from_string = frozenset(my_string)
print(f"From string: {fset_from_string}") # Output: From string: frozenset({'o', 'h', 'l', 'e'})
# Creating an empty frozenset
empty_fset = frozenset()
print(f"Empty frozenset: {empty_fset}") # Output: Empty frozenset: frozenset()
Note: If you try to create a frozenset from a set, you get a frozenset object.
my_set = {10, 20, 30}
fset_from_set = frozenset(my_set)
print(f"From set: {fset_from_set}") # Output: From set: frozenset({10, 20, 30})
Key Differences: set vs. frozenset
This table clearly summarizes the differences:
| Feature | set (Mutable) |
frozenset (Immutable) |
|---|---|---|
| Mutability | Mutable. Can be changed after creation. | Immutable. Cannot be changed after creation. |
| Adding Elements | my_set.add(4) |
Not possible. Raises an AttributeError. |
| Removing Elements | my_set.remove(3) or my_set.discard(3) |
Not possible. Raises an AttributeError. |
| Modification | my_set.update([5, 6]) |
Not possible. Raises an AttributeError. |
| Use as Key | No. Cannot be a key in a dictionary. | Yes. Can be a key in a dictionary or an element in another set. |
| Hashable | No. Not hashable. | Yes. Hashable. |
Why Use a frozenset? (The Main Use Cases)
The primary reason to use a frozenset is its immutability, which makes it hashable. This unlocks two powerful use cases:
Use Case 1: As a Key in a Dictionary
Regular sets are unhashable and cannot be dictionary keys. Since frozensets are hashable, they can be.
# A regular set cannot be a key
# my_dict = { {1, 2}: "value" } # TypeError: unhashable type: 'set'
# A frozenset CAN be a key
fset_key = frozenset([1, 2, 3])
my_dict = {
frozenset([1, 2, 3]): "First Value",
frozenset([4, 5, 6]): "Second Value"
}
print(my_dict[fset_key]) # Output: First Value
Use Case 2: As an Element in Another Set
You can't put a mutable set inside another set. But you can put an immutable frozenset inside another set.
# A regular set cannot be an element in another set
# outer_set = { {1, 2}, {3, 4} } # TypeError: unhashable type: 'set'
# A frozenset CAN be an element in a set
fset1 = frozenset([1, 2])
fset2 = frozenset([3, 4])
outer_set = {fset1, fset2}
print(outer_set) # Output: {frozenset({1, 2}), frozenset({3, 4})}
Common Operations and Methods
Since frozensets are immutable, they only have read-only methods. Any method that would modify the set is absent.
| Operation/Method | Description | Example (s = frozenset([1, 2, 3])) |
|---|---|---|
len(s) |
Returns the number of elements in the frozenset. |
len(s) returns 3 |
for item in s: |
Iterates over the elements in the frozenset. |
for item in s: print(item) prints 1, 2, 3 (order not guaranteed) |
item in s |
Checks if an element is present (membership test). | 2 in s returns True |
s.issubset(other) |
Checks if s is a subset of other. |
s.issubset(frozenset([1, 2, 3, 4])) returns True |
s.issuperset(other) |
Checks if s is a superset of other. |
s.issuperset(frozenset([1, 2])) returns True |
s.isdisjoint(other) |
Checks if s has no elements in common with other. |
s.isdisjoint(frozenset([4, 5])) returns True |
s.union(other) |
Returns a new frozenset with elements from both s and other. |
s.union(frozenset([3, 4, 5])) returns frozenset({1, 2, 3, 4, 5}) |
s.intersection(other) |
Returns a new frozenset with elements common to both s and other. |
s.intersection(frozenset([2, 3, 4])) returns frozenset({2, 3}) |
s.difference(other) |
Returns a new frozenset with elements in s but not in other. |
s.difference(frozenset([2, 3])) returns frozenset({1}) |
s.symmetric_difference(other) |
Returns a new frozenset with elements in either s or other but not both. |
s.symmetric_difference(frozenset([3, 4])) returns frozenset({1, 2, 4}) |
s.copy() |
Returns a shallow copy of the frozenset. (Since it's immutable, it's often the same object). |
s.copy() returns frozenset({1, 2, 3}) |
Important: Notice that methods like union, intersection, etc., return a new frozenset and do not modify the original one.
When to Choose set vs. frozenset
Choose a set when... |
Choose a frozenset when... |
|---|---|
| You need a collection of unique items. | You need a collection of unique items that won't change. |
| You need to frequently add or remove items. | You need the collection to be used as a dictionary key. |
| You are performing set operations (union, intersection) and want to modify the original set. | You need the collection to be an element in another set. |
| Memory is a concern and you don't need hashability. | You want a guarantee that the data cannot be altered. |
Summary
frozenset() is a specialized but very useful data structure in Python. Its immutability makes it hashable, which is the key to its two main advantages: serving as a dictionary key and an element within another set. When you have data that is a collection of unique items and must remain constant, frozenset is the perfect choice.
