Python Immutable Data Structures – Tuples, frozenset, and More
Introduction – Why Use Immutable Data Structures?
In Python, most built-in data types are mutable (e.g., lists, dictionaries, sets). This means their contents can be modified after creation—which can lead to:
- Unexpected side effects
- Hard-to-debug state changes
- Unsafe concurrent behavior
Immutable data structures, on the other hand:
- Cannot be changed after creation
- Are hashable and usable as dictionary keys or set elements
- Improve predictability, thread safety, and functional purity
In this guide, you’ll learn:
- What immutability means in Python
- Built-in immutable types
- How to create custom immutable data structures
- Third-party tools like
namedtupleandpyrsistent - Best practices and use cases
What Does Immutable Mean in Python?
An immutable object is one whose state cannot change after it is created.
Built-in Immutable Types
| Type | Mutable? | Example |
|---|---|---|
int, float, str | Immutable | x = 5, s = "hello" |
tuple | Immutable | (1, 2, 3) |
frozenset | Immutable | frozenset({1, 2, 3}) |
bytes | Immutable | b"data" |
Example: Immutable tuple
data = (1, 2, 3)
data[0] = 10 # TypeError: 'tuple' object does not support item assignment
Tuples prevent accidental mutation.
Immutable vs Mutable – Table Comparison
| Feature | Immutable Types | Mutable Types |
|---|---|---|
| Can change after creation | No | Yes |
| Hashable | Yes | Usually not |
| Thread-safe | Generally | Without locks |
| Safer in functions | Yes | Risk of side effects |
frozenset – Immutable Set
fset = frozenset([1, 2, 3])
fset.add(4) # AttributeError: 'frozenset' object has no attribute 'add'
Use frozenset when you need a set but don’t want it modified.
Creating Custom Immutable Structures
Using namedtuple
from collections import namedtuple
Point = namedtuple("Point", "x y")
p = Point(10, 20)
print(p.x) # 10
p.x = 5 # AttributeError: can't set attribute
Lightweight and immutable—perfect for read-only objects.
Using @dataclass(frozen=True) in Python 3.7+
from dataclasses import dataclass
@dataclass(frozen=True)
class Config:
host: str
port: int
c = Config("localhost", 8080)
# c.port = 80 # FrozenInstanceError
Enforces immutability with a frozen dataclass.
Third-Party Immutable Libraries
pyrsistent – Persistent/Immutable Data Structures
pip install pyrsistent
from pyrsistent import pvector
v = pvector([1, 2, 3])
v2 = v.append(4)
print(v) # pvector([1, 2, 3])
print(v2) # pvector([1, 2, 3, 4])
Functional style: original structure is untouched.
immutables (by MagicStack)
pip install immutables
import immutables
mapping = immutables.Map({"a": 1})
new_map = mapping.set("b", 2)
print(mapping) # immutables.Map({'a': 1})
print(new_map) # immutables.Map({'a': 1, 'b': 2})
Efficient and safe mapping for concurrent programs.
Benefits of Immutability
| Benefit | Why It Matters |
|---|---|
| Predictable behavior | No hidden side effects |
| Safer concurrency | No need for locks on immutable objects |
| Hashability | Can be used as keys in dicts or set items |
| Reusability | Shared safely without copies |
| Functional programming | Aligns with stateless, declarative style |
Real-World Use Case – Safe Function Parameters
def process_data(data: tuple[int, int]):
return data[0] + data[1]
result = process_data((10, 20)) # Immutable input
Functions that accept immutable inputs are safe from mutation bugs.
Best Practices
| Do This | Avoid This |
|---|---|
Use tuple instead of list for constants | Modifying global mutable defaults |
Use @dataclass(frozen=True) for configs | Using mutable dataclasses for read-only data |
Favor frozenset for static sets | Using set() for constants |
| Use third-party libraries for complex needs | Reinventing immutable containers |
Summary – Recap & Next Steps
Immutable data structures provide stability, safety, and performance benefits in Python. They prevent side effects and make your code easier to understand and test.
Key Takeaways:
- Tuples, strings, frozensets, and frozen dataclasses are immutable
- Use
namedtupleanddataclass(frozen=True)for simple records - Use libraries like
pyrsistentandimmutablesfor advanced needs - Immutability improves safety, hashability, and concurrency
Real-World Relevance:
Used in config systems, functional programming, safe APIs, data pipelines, and thread-safe code.
FAQ – Immutable Data Structures in Python
Is a Python list immutable?
No. Lists are mutable and can be changed after creation.
Are tuples always safe?
Yes, as long as they don’t contain mutable objects inside.
What is the difference between frozenset and set?
frozensetis immutablesetis mutable and can change at runtime
Can I create immutable dictionaries?
Yes. Use third-party libraries like immutables or custom MappingProxyType.
Why is immutability useful in concurrency?
Immutable objects are inherently thread-safe—they can’t be changed, so no locking is required.
Share Now :
