Ответ
В Python инкапсуляция реализуется через соглашения об именовании, а не через строгие модификаторы доступа, как в Java или C++. Основная идея — дать понять другим разработчикам, какие атрибуты являются внутренними и не предназначены для прямого использования.
Соглашения об именовании
1. Одинарное подчеркивание (_): Защищенные (Protected) атрибуты
- Соглашение:
_variable— это подсказка, что атрибут или метод предназначен для внутреннего использования внутри класса или его наследников. - Поведение: Интерпретатор никак не ограничивает доступ. Атрибут не импортируется при
from module import *.
2. Двойное подчеркивание (__): Приватные (Private) атрибуты
- Соглашение:
__variableиспользуется, чтобы избежать случайного переопределения атрибута в дочерних классах. - Поведение: Python применяет механизм "искажения имен" (name mangling), преобразуя имя в
_ClassName__variable. Это делает доступ извне сложнее, но не невозможным.
Пример
class MyClass:
def __init__(self):
self.public = "Я публичный"
self._protected = "Я защищенный"
self.__private = "Я приватный"
def print_private(self):
# Внутри класса доступ прямой
print(self.__private)
obj = MyClass()
# Доступ к публичному атрибуту - OK
print(obj.public)
# Доступ к защищенному - технически возможно, но не рекомендуется
print(obj._protected)
# Прямой доступ к приватному вызовет ошибку
try:
print(obj.__private)
except AttributeError as e:
print(e) # 'MyClass' object has no attribute '__private'
# Доступ через искаженное имя - возможен, но нарушает инкапсуляцию
print(obj._MyClass__private)
Лучшие практики
- Используйте
_для всех внутренних атрибутов, которые не являются частью публичного API вашего класса. - Используйте
__очень редко, в основном для предотвращения конфликтов имен в сложных иерархиях наследования. - Для управляемого доступа к данным (getters/setters) используйте декоратор
@property.
Ответ 18+ 🔞
Ах ты ж, питон, сука, блядь! Ну и цирк с инкапсуляцией у тебя, ёпта! Не как у этих серьёзных дядек в Java, где всё по струнке — private, protected, и хрен тебе, а не доступ. Тут всё на доверии, как в хорошей коммуналке: вроде и своё есть, но сосед может зайти, если очень надо, блядь.
Смотри сюда, как тут всё устроено, этот ваш «джентельменский договор», пиздец.
Одинарное подчёркивание (_) — это типа «руками не трогать, а то обосрёшься»
Ну то есть пишешь _variable — и все вроде как умные люди должны понять: «Опа, это внутренняя кухня класса, лезть не стоит, а то потом автор кода приедет и ебальник набьёт». Сам питон на это вообще похуй — обратиться можно, он не ругнется. Но если сделаешь from module import *, то эту переменную он тебе не притащит, типа «сам дурак, я тебе не служба доставки внутренностей».
Двойное подчёркивание (__) — это уже «ну ты ваще охренел?»
Вот это __variable — это уже посерьёзнее, блядь. Питон видит это и такой: «Ага, ща мы этого умника проучим». И включает name mangling, ёбаный в рот! То есть он берёт и переименовывает твой атрибут в _ИмяКласса__variable. Не конфликтовать, понимаешь ли, в наследниках! Доступ-то всё равно есть, если очень упороться и знать пароль, но уже надо попотеть, сука.
Смотри, как это выглядит вживую, чтоб ты проникся:
class MyClass:
def __init__(self):
self.public = "Я публичный — всем сестрам по серьгам"
self._protected = "Я защищённый — вроде и твоё, но не тыкай"
self.__private = "Я приватный — иди нахуй, вообще-то"
def print_private(self):
# А внутри класса — пожалуйста, родной, бери
print(self.__private)
obj = MyClass()
# С публичным всё ясно — бери, не хочу
print(obj.public)
# К защищённому — ну ладно, технически можно, но совесть зазрит, пидарас
print(obj._protected)
# А вот с приватным — обломись, питон притворяется, что не понимает
try:
print(obj.__private)
except AttributeError as e:
print(e) # 'MyClass' object has no attribute '__private'. Ну конечно нет, блядь!
# Но если ты хитрожопый и знаешь секретное имя — welcome, ёпта!
print(obj._MyClass__private) # Вот он я, приватный, блядь!
Так как жить-то, спрашивается?
Да по-человечески, блядь!
_— юзай для всего, что внутри работает, а наружу светить не должно. Это как трусы — они есть, но показывать не надо.__— это уже на случай, если у тебя там наследники как тараканы расплодились, и имена конфликтуют. Штука редкая, как честный политик.- А если тебе реально нужно дать доступ к чему-то с проверками — вспоминай про
@property, это ж святое! Чтоб не писатьobj.set_value(10), а сделатьobj.value = 10, но внутри всё по правилам. Красота, блядь, а не жизнь!
Вот и вся философия. Никаких замков, только намёки и договорняки. А кто лезет, куда не просят — тот сам потом разгребает, почему у него всё ебнулось.