Как в Python создать приватный атрибут в классе

Ответ

В 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)

Соглашения об именовании

  1. _single_leading_underscore (одно подчёркивание):

    • Назначение: Сигнал для других разработчиков, что атрибут или метод предназначен для внутреннего использования (аналог protected).
    • Поведение: Никакого специального синтаксического поведения. Доступ не ограничивается.
  2. __double_leading_underscore (два подчёркивания):

    • Назначение: Имитация приватности и предотвращение конфликтов имён при наследовании.
    • Поведение: Включается механизм искажения имён (name mangling).

Ответ 18+ 🔞

А, слушай, про эти ваши подчёркивания в питоне! Ну, типа, как у нас в стране — полной приватности, блядь, не бывает, но можно сделать вид, что она есть.

Вот смотри, в Java или C++ там прям строго: private — и хрен тебе, а не доступ. А в Python — это всё театр, ёпта, один сплошной договорняк. Но договорняк, блядь, удобный!

Как эта хуйня работает

Хочешь сделать атрибут как бы приватным? Начинай его имя с двух подчёркиваний __. Интерпретатор, хитрая жопа, увидит это и скажет: «Ага, щас мы его спрячем!». И переименует его, добавив в начало _ИмяКласса.

  • Было __secret в классе MyClass? Стало _MyClass__secret.

Извне по имени __secret его уже не найдёшь — ну, чтобы какой-нибудь распиздяй в дочернем классе случайно не перезаписал.

Смотри, как это выглядит в деле

class MyClass:
    def __init__(self):
        self.public_attr = "Я на виду, как говно в проруби"
        self._protected_attr = "Я как бы для своих (но зайди, если очень надо)"
        self.__private_attr = "А я типа приватный (имя мне поменяли)"

    def get_private_attr(self):
        return self.__private_attr

obj = MyClass()

# К публичному — всегда добро пожаловать
print(obj.public_attr)  # -> Я на виду, как говно в проруби

# Попробуй напрямую к приватному — получишь по ебалу
try:
    print(obj.__private_attr)
except AttributeError as e:
    print(e)  # -> 'MyClass' object has no attribute '__private_attr'. Ну я же говорил!

# Но если ты, блядь, настырный и знаешь секретное имя — то вот оно, родимое
print(obj._MyClass__private_attr)  # -> А я типа приватный (имя мне поменяли)

А теперь про негласные правила, которые все блядь соблюдают

  1. Одно подчёркивание _variable:

    • Что значит: «Чувак, это внутренняя кухня. Трогать можно, но если сломаешь — сам дурак». Типа protected.
    • По факту: Никакой магии, просто все видят подчёркивание и делают умное лицо.
  2. Два подчёркивания __variable:

    • Что значит: «Я серьёзно, не лезь. И да, чтобы имена в наследниках не конфликтовали, нахуй».
    • По факту: Включается тот самый «мангинг» (name mangling), когда имя подменяется. Не приватность, а так, защита от дурака. Очень, кстати, годная штука.

Короче, вся система держится на честном слове и паре символов. Красиво, блядь!