Вопрос проверяет понимание внутреннего механизма заморозки датаклассов в Python и того, как именно реализуется запрет на изменение полей.
Когда вы создаете датакласс с параметром frozen=True, Python генерирует специальный класс, который предотвращает изменение атрибутов после инициализации. Это достигается за счет переопределения метода __setattr__.
При использовании декоратора @dataclass(frozen=True), Python автоматически добавляет в класс метод __setattr__, который вызывает исключение FrozenInstanceError при попытке изменить атрибут. Однако во время выполнения __init__ этот метод временно отключается, чтобы можно было установить начальные значения.
from dataclasses import dataclass
@dataclass(frozen=True)
class Point:
x: int
y: int
p = Point(1, 2)
# p.x = 3 # Вызовет FrozenInstanceErrorВнутренне Python использует механизм, который позволяет методу __init__ устанавливать атрибуты, игнорируя блокировку. Это делается через прямой вызов object.__setattr__ внутри сгенерированного __init__. После завершения инициализации любые попытки изменить атрибуты через обычное присваивание приводят к ошибке.
Использование frozen=True полезно для создания неизменяемых объектов, что повышает безопасность и предсказуемость кода, особенно в многопоточных средах или при работе с хешируемыми объектами.