На самом деле нет 100% водонепроницаемого способа, но вы можете затруднить непреднамеренное изменение объекта, который хотите сохранить замороженным;рекомендуемый способ для большинства людей, вероятно, использовать замороженный DataClass
или замороженный attrs
класс
В своем докладе о DataClasses (2018),@RaymonHettinger упоминает три подхода: один способ - с метаклассом , другой - как в модуле фракций - для атрибутов свойство только для чтения ;DataClass
модуль расширяет __setattr__
и __delattr__
и переопределяет __hash__
:
-> использовать метакласс.
Хорошие ресурсы включают книги @DavidBeasleyи говорит на python.
-> дает атрибутам свойство только для чтения
class SimpleFrozenObject:
def __init__(self, x=0):
self._x = x
@property
def x(self):
return self._x
f = SimpleFrozenObject()
f.x = 2 # raises AttributeError: can't set attribute
-> extended __setattr__
и __delattr__
и переопределяет ` hash
class FrozenObject:
...
def __setattr__(self, name, value):
if type(self) is cls or name in (tuple of attributes to freeze,):
raise FrozenInstanceError(f'cannot assign to field {name}')
super(cls, self).__setattr__(name, value)
def __delattr__(self, name):
if type(self) is cls or name in (tuple of attributes to freeze,):
raise FrozenInstanceError(f'cannot delete field {name}')
super(cls, self).__delattr__(name, value)
def __hash__(self):
return hash((tuple of attributes to freeze,))
...
Библиотека attrs
также предлагает варианты создания неизменяемых объектов.