オーバーライドのパフォーマンスへの影響については__setattr__
、どの回答にも言及されていません。これは、多くの小さなオブジェクトを作成するときに問題になる可能性があります。(そして__slots__
、パフォーマンスの高いソリューションになりますが、ピクルス/継承を制限します)。
だから私はinitの後に遅いsettatrをインストールするこのバリアントを思いついた:
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): ...
freeze
の最後に呼び出したくない__init__
場合、継承が問題である場合、または継承を望まない場合は、それを適応させることもできます。たとえば、次の回答vars()
に基づくデコレータバージョンです。pystrict
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: ...