How to solve the immutability helper problem in Python

In programming, immutability refers to an object whose state can not be changed after creation. Python doesn’t have any built-in functionality to support immutability. We can try to achieve this by:

  • Using forzenset()

  • Using custom classes

  • Using namedtuple()

Using frozenset()

The frozenset(iterable) is an immutable version of a Python set. Here, iterable can be a tuple, dictionary, or set. Consider the example below.

person = {"name": "Anne", "age": 23}
person["age"]=24
# Immutable iterable created from dictionary
imm_dict = frozenset(person)
print(imm_dict)

Explanation

  • Lines 1–2: We create a simple dictionary, person, with two keys. In line 2, we change the value of age to 24. This should work, as a Python dictionary is a mutable iterable.

  • Lines 5–6: We create a frozen set imm_dict via the person dictionary. Notice the output; it only takes the keys of the dictionary to create the frozen (immutable) set.

Another example with the set object is as follows:

odd = {1, 3, 5, 7, 9}
odd.add(11)
print(odd)
# Immutable iterable created from set
imm_set = frozenset(odd)
imm_set.add(11) # Error expected

Explanation

  • Lines 1–3: We create a simple set, odd, which contains odd numbers from 1 to 9. Next, we add 11 to the set using the add() function. The print() (line 3) verifies that a new element was added.

  • Lines 6–7: We create a frozen set imm_set via the odd set. Line 7 shows an expected error because, after creation, we can not add any new element in the imm_set object which is a frozen (immutable) set.

Using custom classes

To achieve immutability, we can create our class with read-only properties. Consider an example below.

# Custom class with read-only properties
class Immutable:
def __init__(self, obj1, obj2):
self._obj1 = obj1
self._obj2 = obj2
@property
def obj1(self): # Getter for obj1
return self._obj1
@property
def obj2(self): # Getter for obj2
return self._obj2
# Main
immutable = Immutable(4, 3)
print(immutable.obj1) # Reading obj1
print(immutable.obj2) # Reading obj2

Explanation

  • Lines: 3–5: The constructor implies that every object of Immutable type will have two attributes: obj1 and obj2.

  • Lines 7–9: The @property decorator is simply a Pythonic way to use getters/setters. Here, obj1(self) is a getter that returns the value of obj1.

  • Lines 11–13: Here, obj2(self) is a getter that returns the value of obj2.

  • Lines 17–19: We create an object of Immutable type, immutable. Next, we simply call the getters on obj1 and obj2, which print 4 and 3, respectively.

Note: There is no way to change the values of attributes, after an object is created.

Using namedtuple()

The namedtuple() is a lightweight way to create an immutable object without creating a custom class. This function creates a simple class with named attributes. Below is an example:

# Import from collections module
from collections import namedtuple
# Creating a namedtuple
Immutable = namedtuple('Immutable', ['obj1', 'obj2'])
immutable= Immutable(obj1=4, obj2=3) # Object created with type immutable (namedtuple)
print(immutable.obj1)
print(immutable.obj2)
#immutable.obj1=5 # Error expected

Try uncommenting line 11. Notice the error because we can not change the attributes after creation.

Explanation

  • Line 1: We import the namedtuple() function and the collections module.

  • Line 5–6: We create a namedtuple called Immutable with two fields: obj1 and obj2. Next, we create an object, immutable of Immutable type and assign values to fields.

  • Line 8–9: The namedtuple type objects are hashable. We print the values of immutable fields, obj1 and obj2, which print 4 and 3, respectively.


Free Resources

Copyright ©2025 Educative, Inc. All rights reserved