Writing a class that is really immutable in Python is really hard, if not impossible.
Currently I’m playing a little creating an immutable version of dict. To ensure “real” immutability, I had to:
- create a function
_setattr()
, in this horrible way:
def _setattr(self, *args, **kwargs):
"""
not implemented
"""
if inspect.stack()[1].filename == __file__:
object.__setattr__(self, *args, **kwargs)
else :
raise NotImplementedError(self._immutable_err)
In this way, I created a class with all its members private. And I had to use inspect.stack()
that is not guaranteed to work on every Py implementation…
To make it working, the trick is overriding __new__()
:
def __new__(klass, *args, **kwargs):
try:
klass.__setattr__ = object.__setattr__
except Exception:
pass
self = super().__new__(klass)
self._initialized = False
and in __init__()
, write:
def __init__(self, *args, **kwargs):
self._klass = type(self)
self._klass_name = self._klass.__name__
self._immutable_err = "'{klass}' object is immutable".format(klass=self._klass_name)
if self._initialized:
raise NotImplementedError(self._immutable_err)
[...]
self._initialized = True
self._klass.__setattr__ = self._klass._setattr
- use
__slots__
, which for what I know are a bit problematic when you inherit a class - override
__delattr__
so it raisesNotImplementedError
And after all of this, I’m not really sure you can’t do some trick to mutate the object anyway…
I mean, all this mess could be avoided, if Python, like all the other OO languages, implements private
. Why Python decided to not implement a normal OO visibility of the members of a class?