Skip to content

Instantly share code, notes, and snippets.

@microamp
Last active October 16, 2023 05:30
Show Gist options
  • Save microamp/9d8e3359bcadd7dca6a8 to your computer and use it in GitHub Desktop.
Save microamp/9d8e3359bcadd7dca6a8 to your computer and use it in GitHub Desktop.
How to make immutable classes in Python
#-*- coding: utf-8 -*-
from collections import namedtuple
class Immutable(namedtuple("Immutable", "x, y")):
"""Immutable class using collections.namedtuple."""
def __str__(self):
return "class: {c}, x: {x}, y: {y}".format(c=Immutable.__name__,
x=self.x, y=self.y)
class Immutable2(tuple):
"""Immutable class using tuple."""
def __new__(cls, x, y):
return tuple.__new__(cls, (x, y,))
@property
def x(self):
return tuple.__getitem__(self, 0)
@property
def y(self):
return tuple.__getitem__(self, 1)
def __str__(self):
return "class: {c}, x: {x}, y: {y}".format(c=Immutable2.__name__,
x=self.x, y=self.y)
class Immutable3(object):
"""Immutable class without overriding collections.namedtuple/tuple."""
__slots__ = ("x", "y",)
def __init__(self, x, y):
object.__setattr__(self, "x", x)
object.__setattr__(self, "y", y)
def __setattr__(self, *args):
raise AttributeError("Attributes of Immutable3 cannot be changed")
def __delattr__(self, *args):
raise AttributeError("Attributes of Immutable3 cannot be deleted")
def __str__(self):
return "class: {c}, x: {x}, y: {y}".format(c=Immutable3.__name__,
x=self.x, y=self.y)
if __name__ == "__main__":
i1 = Immutable(1, 2)
print(str(i1))
try:
i1.x = 3 # will fail
except Exception:
print("error while setting attribute of "
"{0} object".format(Immutable.__name__))
i2 = Immutable2(10, 20)
print(str(i2))
try:
i2.x = 30 # will fail
except Exception:
print("error while setting attribute of "
"{0} object".format(Immutable2.__name__))
i3 = Immutable3(100, 200)
print(str(i3))
try:
i3.x = 300 # will fail
except Exception:
print("error while setting attribute of "
"{0} object".format(Immutable3.__name__))
@arfsufpe
Copy link

arfsufpe commented Jan 28, 2020

Congrats for the example. I tried using the first example.
But I still have one question: how would I call a "check" method in the constructor and raise an error in case the args were incosistent.
For example:
Checking an ISS last two digits to see whether it is correct and raise an error (case the last two digits is not correct).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment