# How to Create Immutable Python Objects: A Comprehensive Guide
Written on
Chapter 1: Understanding Mutability in Python
In Python, mutability refers to the ability of an object to be changed after its creation. When you want to ensure that your Python objects remain unchanged, you need to implement immutability. This guide will help you understand how to create immutable objects effectively.
A Standard Mutable Class
Let’s examine a typical mutable class using a Dog example:
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
dog = Dog('rocky', 5)
print(dog.name) # rocky
print(dog.age) # 5
In this example, the Dog class allows for changes to the attributes:
dog.name = 'fifi'
print(dog.name) # fifi
To prevent users from altering attributes, you can implement immutability in various ways.
Section 1.1: Modifying the __setattr__ Method
The __setattr__ magic method is invoked when setting an attribute on an object. You can override this method to raise an error when an attempt is made to modify an attribute:
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def __setattr__(self, key, value):
raise AttributeError('Dog is immutable!!')
dog = Dog('rocky', 4)
Attempting to change dog.name would result in:
AttributeError: Dog is immutable!!
To properly initialize attributes without triggering the error, you must call object.__setattr__:
class Dog:
def __init__(self, name, age):
object.__setattr__(self, 'name', name)
object.__setattr__(self, 'age', age)
def __setattr__(self, key, value):
raise AttributeError('Dog is immutable!!')
Now, if you try to change dog.name, you will receive the same error.
Section 1.2: Protecting the __dict__ Attribute
Even with the previous protections, users can manipulate the .__dict__ attribute directly:
dog.__dict__['name'] = 'fifi'
print(dog.name) # fifi
To prevent this, you can create a read-only property for .__dict__:
class Dog:
def __init__(self, name, age):
object.__setattr__(self, 'name', name)
object.__setattr__(self, 'age', age)
def __setattr__(self, key, value):
raise AttributeError('Dog is immutable!!')
@property
def __dict__(self):
return {}
Now, attempting to access .__dict__ will return an empty dictionary:
dog.__dict__['name'] = 'fifi'
print(dog.name) # rocky
Loophole Alert
While these methods can prevent most modifications, there is still a loophole. The following code can bypass your protections:
object.__setattr__(dog, 'name', 'fifi')
print(dog.name) # fifi
Conclusion
In summary, while you can implement various strategies to make your Python objects immutable, experienced users may still find ways to modify them. If your colleagues or users are unaware of the object.__setattr__ trick, your object should remain safe from alterations.
Chapter 2: Additional Resources
Explore the differences between immutable and mutable objects in Python in this insightful video.
This video simplifies the syntax of mutable and immutable data types in Python, making it easier to understand their applications.
If you appreciate this content, consider supporting my work by engaging with the community! Thank you for your support!