In keiner der Antworten wird die Auswirkung auf die Leistung erwähnt, die das Überschreiben von __setattr__
was bei der Erstellung vieler kleiner Objekte ein Problem darstellen kann. (Und __slots__
wäre die performante Lösung, schränkt aber Pickle/Vererbung ein).
Also habe ich mir diese Variante ausgedacht, die unser langsameres settatr nach init installiert:
class FrozenClass:
def freeze(self):
def frozen_setattr(self, key, value):
if not hasattr(self, key):
raise TypeError("Cannot set {}: {} is a frozen class".format(key, self))
object.__setattr__(self, key, value)
self.__setattr__ = frozen_setattr
class Foo(FrozenClass): ...
Wenn Sie nicht anrufen möchten freeze
am Ende von __init__
wenn die Vererbung ein Problem darstellt oder wenn Sie es nicht in vars()
kann es auch angepasst werden: Hier ist zum Beispiel eine Dekorator-Version, die auf dem pystrict
Antwort:
import functools
def strict(cls):
cls._x_setter = getattr(cls, "__setattr__", object.__setattr__)
cls._x_init = cls.__init__
@functools.wraps(cls.__init__)
def wrapper(self, *args, **kwargs):
cls._x_init(self, *args, **kwargs)
def frozen_setattr(self, key, value):
if not hasattr(self, key):
raise TypeError("Class %s is frozen. Cannot set '%s'." % (cls.__name__, key))
cls._x_setter(self, key, value)
cls.__setattr__ = frozen_setattr
cls.__init__ = wrapper
return cls
@strict
class Foo: ...