I would like to prevent a user of an instance mistakenly creating a non existing attribute when using said object.
Say I have a class with an init and some attributes :
class Foo(obj):
def __init__(self, a, b):
self.a = a
self.b = b
I would like to enable setting existing attributes while preventing the creation of a new attribute:
myobj = foo(1,2)
>>
print(myobj.a)
>> 1
myobj.a = 2
myobj.c = 1
>> AttributeError: frozen instance
That is fairly easy with __setattr__ override and a boolean :
class Foo(obj):
_is_frozen = False
def __init__(self, a, b):
self.a = a
self.b = b
self._is_frozen = True
def __setattr__(self, name, value):
if not self._is_frozen or hasattr(self, name):
super().__setattr__(name, value)
else:
raise AttributeError("frozen instance")
Now the step I struggle with is when a new class inherits Foo. If new attributes must be defined after the call to the super().__init__(), the instance is frozen.
I have tried using decorator to make a metaclass but the decorator of the mother class is still called at the super().__init__() call and I can't define my new attributes.
In other words, is there a way to make a kind of __post_init__ method (reference to the dataclass module) that would only be called after all inits (the one of the class and the ones of the inherited classes) have been called ?