Ответ
В Python нет строгой инкапсуляции и настоящих private атрибутов, как в Java или C++. Вместо этого используется механизм искажения имён (name mangling), который служит сильным соглашением и помогает избежать случайных конфликтов имён в иерархии наследования.
Как это работает
Чтобы объявить атрибут "приватным", его имя должно начинаться с двух подчёркиваний __ (но не заканчиваться ими). Интерпретатор Python автоматически изменяет имя такого атрибута, добавляя к нему префикс _ИмяКласса.
- Атрибут
__private_attrв классеMyClassстанет_MyClass__private_attr.
Это делает атрибут недоступным по его исходному имени извне класса, предотвращая случайное переопределение.
Пример
class MyClass:
def __init__(self):
self.public_attr = "I'm public"
self._protected_attr = "I'm protected (by convention)"
self.__private_attr = "I'm private (mangled)"
def get_private_attr(self):
return self.__private_attr
obj = MyClass()
# Прямой доступ к публичному атрибуту
print(obj.public_attr) # -> I'm public
# Попытка доступа к приватному атрибуту вызовет ошибку
try:
print(obj.__private_attr)
except AttributeError as e:
print(e) # -> 'MyClass' object has no attribute '__private_attr'
# Доступ к "искаженному" имени все еще возможен (но не рекомендуется)
print(obj._MyClass__private_attr) # -> I'm private (mangled)
Соглашения об именовании
-
_single_leading_underscore(одно подчёркивание):- Назначение: Сигнал для других разработчиков, что атрибут или метод предназначен для внутреннего использования (аналог
protected). - Поведение: Никакого специального синтаксического поведения. Доступ не ограничивается.
- Назначение: Сигнал для других разработчиков, что атрибут или метод предназначен для внутреннего использования (аналог
-
__double_leading_underscore(два подчёркивания):- Назначение: Имитация приватности и предотвращение конфликтов имён при наследовании.
- Поведение: Включается механизм искажения имён (
name mangling).