Ответ
Неизменяемый (immutable) объект — это объект, состояние которого нельзя изменить после его создания. Это повышает предсказуемость и безопасность кода, особенно в многопоточных приложениях, а также позволяет использовать объекты в качестве ключей словаря.
В Python есть несколько способов создать неизменяемый класс:
1. @dataclass(frozen=True) (Python 3.7+)
Это самый современный и предпочтительный способ. Декоратор dataclass с параметром frozen=True автоматически делает класс неизменяемым.
from dataclasses import dataclass, FrozenInstanceError
@dataclass(frozen=True)
class Point:
x: int
y: int
p = Point(10, 20)
print(p.x) # 10
try:
p.x = 30 # Попытка изменить атрибут
except FrozenInstanceError as e:
print(e) # Вывод: cannot assign to field 'x'
2. collections.namedtuple
Это фабричная функция для создания простых классов-кортежей. Объекты namedtuple легковесны и неизменяемы по своей природе.
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x) # 10
# Попытка изменения вызовет AttributeError
# p.x = 30 -> AttributeError: can't set attribute
3. Ручная реализация через __slots__ и __setattr__
Этот способ дает полный контроль, но является наиболее многословным. Он полезен для понимания механики неизменяемости.
class ImmutablePoint:
__slots__ = ('x', 'y') # Экономит память и предотвращает создание __dict__
def __init__(self, x, y):
# Используем object.__setattr__ для инициализации полей
super().__setattr__('x', x)
super().__setattr__('y', y)
def __setattr__(self, name, value):
# Переопределяем метод, чтобы запретить изменения
raise AttributeError(f"Can't modify attribute {name}")