Какие механизмы инкапсуляции реализованы в Python?
Что проверяют
Знаете ли вы, что в Python нет модификаторов доступа как в Java, и можете ли объяснить, на чём тогда держится инкапсуляция. Следом почти всегда спрашивают, что такое name mangling и можно ли всё-таки достучаться до атрибута с двумя подчёркиваниями.
Как отвечать
Сформулируйте главное: инкапсуляция в Python держится на соглашениях и на протоколе доступа к атрибутам, а не на запретах интерпретатора.
- одно подчёркивание
_name: внутренняя деталь, трогать снаружи не принято. Интерпретатор не мешает, но линтеры подсветят обращение, аfrom module import *такие имена не импортирует; - два подчёркивания
__name: name mangling, внутри класса имя превращается в_ClassName__name. Цель не спрятать, а избежать случайного конфликта имён с подклассами. Снаружи атрибут доступен какobj._ClassName__name; @property: геттер, сеттер и делитер с синтаксисом обычного атрибута. Можно начать с публичного поля и добавить проверку позже, не ломая вызывающий код;- дескрипторы: объекты с
__get__и__set__, на которых построеныproperty,classmethodи поля ORM. Повторяющуюся валидацию можно вынести в один класс; __slots__: фиксирует набор атрибутов, запрещает заводить новые и экономит память на экземплярах;@dataclass(frozen=True)иNamedTuple: неизменяемые объекты, где защита следует из невозможности менять состояние;__all__и замыкания: контроль публичного API модуля и состояние, недоступное снаружи функции.
Хорошо добавить тезис из культуры языка: «мы все здесь взрослые люди». Python доверяет разработчику, а границы API обозначаются именами и документацией.
Где спотыкаются
Называют __name приватным атрибутом, который нельзя прочитать. Это неправда, достаточно знать искажённое имя.
Пишут в стиле Java get_value() и set_value() на каждое поле. В Python это лишнее: пока логики нет, хватает публичного атрибута, а когда она появится, его заменит property.
Путают __name с __name__. Имена с двумя подчёркиваниями с обеих сторон это dunder-методы и атрибуты, name mangling к ним не применяется.