The frozenset([iterable]) built-in function creates an immutable, hashable set object containing unique elements from an iterable.
Immutable Sets & Dictionary Keys: While standard set objects are mutable and unhashable, frozenset instances cannot be modified after creation. This makes them hashable, allowing them to serve as dictionary keys or elements inside other sets. To create mutable sets, see set(), or convert to read-only sequences with tuple().
The frozenset() constructor accepts an optional iterable:
# Formal syntax of built-in frozenset()
frozen_set = frozenset([iterable])
| Parameter | Type Accepted | Behavioral Details |
|---|---|---|
iterable |
Iterable[T] (optional) |
Any iterable collection (list, tuple, string, set). Elements must be hashable. |
| Return Value | frozenset object |
An immutable, hashable set containing distinct elements. Empty if omitted. |
Passing an iterable deduplicates items. Once created, attempts to add or delete elements raise an AttributeError:
# 1. Creating a frozenset from a list with duplicate elimination
values = [1, 2, 3, 2, 1]
frozen = frozenset(values)
print("frozenset content: ", frozen) # frozenset({1, 2, 3})
print("frozenset type: ", type(frozen)) #
# 2. Immutable integrity: attempts to modify raise AttributeError
try:
frozen.add(4)
except AttributeError as err:
print("AttributeError caught:", err)
Output:
frozenset content: frozenset({1, 2, 3})
frozenset type:
AttributeError caught: 'frozenset' object has no attribute 'add'
Standard mathematical set operators (|, &, -, ^) function identically to regular sets, returning newly allocated frozensets:
# Mathematical set operations (all return new frozenset instances)
A = frozenset({1, 2, 3})
B = frozenset({3, 4, 5})
print("Union (A | B): ", A | B)
print("Intersection (A & B): ", A & B)
print("Difference (A - B): ", A - B)
print("Symmetric Difference (A ^ B):", A ^ B)
Output:
Union (A | B): frozenset({1, 2, 3, 4, 5})
Intersection (A & B): frozenset({3})
Difference (A - B): frozenset({1, 2})
Symmetric Difference (A ^ B): frozenset({1, 2, 4, 5})
Because frozenset implements __hash__(), it solves the fundamental problem of using order-independent collections as dictionary keys or elements inside nested sets:
# Using frozenset as dictionary keys and inside sets
# Because frozenset is hashable, order-independent composite keys succeed!
permissions = {
frozenset({'read', 'write'}): 'editor',
frozenset({'read'}): 'viewer',
frozenset({'read', 'write', 'admin'}): 'administrator'
}
# Lookup works regardless of key insertion order
query_role = frozenset({'write', 'read'})
print("Role for {'write', 'read'}:", permissions[query_role])
# Storing sets inside another set
nested_sets = {frozenset({1, 2}), frozenset({3, 4})}
print("Set of frozensets count: ", len(nested_sets))
Output:
Role for {'write', 'read'}: editor
Set of frozensets count: 2
The difference between mutable sets and frozensets mirrors the relationship between lists and tuples:
| Feature | set |
frozenset |
|---|---|---|
| Mutability | Mutable (supports .add(), .remove()) |
Immutable (read-only after creation) |
| Hashable | No (raises TypeError: unhashable type) |
Yes (if all contained items are hashable) |
| Dictionary Key | Cannot be a dict key | Valid dictionary key |
| Nested in Sets | Cannot be added to another set | Can be added to sets and frozensets |
| Literal Syntax | {1, 2, 3} |
Must use constructor frozenset({1, 2, 3}) |
# set vs frozenset: mutability, hashability, and memory
s = {1, 2, 3}
fs = frozenset({1, 2, 3})
print("hash(frozenset):", hash(fs)) # Integer hash code
try:
hash(s) # TypeError: unhashable type: 'set'
except TypeError as err:
print("hash(set) error:", err)
Output:
hash(frozenset): -7699079583225444929
hash(set) error: unhashable type: 'set'
Below are real-world recipes utilizing frozenset for function memoization and static security permissions:
# Recipe A: Memoizing functions with set arguments
from functools import lru_cache
@lru_cache(maxsize=128)
def calculate_tax(items_set: frozenset) -> float:
# frozenset allows caching calls where item order doesn't matter
tax_rates = {"electronics": 0.08, "clothing": 0.05, "food": 0.0}
return sum(tax_rates.get(item, 0.05) for item in items_set)
cart_a = frozenset(["electronics", "clothing"])
cart_b = frozenset(["clothing", "electronics"]) # Same order-independent set!
print("Tax for cart A:", calculate_tax(cart_a))
print("Tax for cart B:", calculate_tax(cart_b))
print("Cache hits: ", calculate_tax.cache_info().hits)
# Recipe B: Read-only global permissions configuration
ADMIN_CAPABILITIES = frozenset(["CREATE_USER", "DELETE_USER", "VIEW_LOGS"])
print("Is 'DELETE_USER' permitted:", "DELETE_USER" in ADMIN_CAPABILITIES)
Output:
Tax for cart A: 0.13
Tax for cart B: 0.13
Cache hits: 1
Is 'DELETE_USER' permitted: True
frozenset([[1, 2]])) raises TypeError: unhashable type: 'list'. Inner elements must be hashable primitives, tuples, or other frozensets.A + B raises TypeError. Use the union operator A | B or A.union(B).frozen[0] raises TypeError: 'frozenset' object is not subscriptable.# Pitfall 1: Attempting to store unhashable elements inside a frozenset
try:
# A list is unhashable, so it cannot be placed inside a frozenset!
bad_fs = frozenset([[1, 2], [3, 4]])
except TypeError as err:
print("TypeError caught:", err)
# Correct approach: convert inner containers to tuples or frozensets
good_fs = frozenset([(1, 2), (3, 4)])
print("Valid nested frozenset:", good_fs)
# Pitfall 2: Using '+' instead of '|' for union
try:
frozenset({1}) + frozenset({2})
except TypeError as err:
print("Plus operator error: ", err)
Output:
TypeError caught: unhashable type: 'list'
Valid nested frozenset: frozenset({(1, 2), (3, 4)})
Plus operator error: unsupported operand type(s) for +: 'frozenset' and 'frozenset'
Practice frozenset operations, composite dictionary keys, and memoization in our companion Jupyter Notebook:
Explore interactive code cells, benchmark set operations, build cached calculation engines, and run self-validating assertions.
View on GitHub Run in Google ColabRun these unit checks directly in Python or your local environment to verify frozenset() mechanics:
def test_frozenset_mechanics():
# 1. Deduplication
fs = frozenset([1, 2, 2, 3])
assert len(fs) == 3
assert 2 in fs
# 2. Immutability
assert not hasattr(fs, "add")
assert not hasattr(fs, "remove")
# 3. Hashability
d = {frozenset([1, 2]): "pair"}
assert d[frozenset([2, 1])] == "pair"
# 4. Set operations
A = frozenset([1, 2])
B = frozenset([2, 3])
assert A | B == frozenset([1, 2, 3])
assert A & B == frozenset([2])
print("All frozenset() unit assertions passed! 100% verified.")
test_frozenset_mechanics()
Output:
All frozenset() unit assertions passed! 100% verified.
Creates mutable, dynamic set of unique hashable elements.
Constructs immutable ordered sequences of elements.
Constructs key-value associative mapping collections.
Calculates the integer hash value of immutable objects.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.