Skip to content
Advertisement

How to make an immutable object in Python?

Although I have never needed this, it just struck me that making an immutable object in Python could be slightly tricky. You can’t just override __setattr__, because then you can’t even set attributes in the __init__. Subclassing a tuple is a trick that works:

JavaScript

But then you have access to the a and b variables through self[0] and self[1], which is annoying.

Is this possible in Pure Python? If not, how would I do it with a C extension?

(Answers that work only in Python 3 are acceptable).

Update:

As of Python 3.7, the way to go is to use the @dataclass decorator, see the newly accepted answer.

Advertisement

Answer

Using a Frozen Dataclass

For Python 3.7+ you can use a Data Class with a frozen=True option, which is a very pythonic and maintainable way to do what you want.

It would look something like that:

JavaScript

As type hinting is required for dataclasses’ fields, I have used Any from the typing module.

Reasons NOT to use a Namedtuple

Before Python 3.7 it was frequent to see namedtuples being used as immutable objects. It can be tricky in many ways, one of them is that the __eq__ method between namedtuples does not consider the objects’ classes. For example:

JavaScript

As you see, even if the types of obj1 and obj2 are different, even if their fields’ names are different, obj1 == obj2 still gives True. That’s because the __eq__ method used is the tuple’s one, which compares only the values of the fields given their positions. That can be a huge source of errors, specially if you are subclassing these classes.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement