В чем разница между одинарным и двойным подчеркиванием в Python

Ответ

В Python одинарное (_) и двойное (__) подчеркивание перед именем атрибута или метода — это соглашения, которые влияют на видимость и разрешение имен, но не обеспечивают настоящей защиты или приватности.

Одинарное подчеркивание (_name)

  • Семантика: "Защищенный" (protected) член. Это сигнал разработчику: "Этот атрибут/метод предназначен для внутреннего использования в классе или его подклассах. Не используйте его напрямую извне, если не понимаете последствий".
  • Поведение: Никаких технических ограничений. Доступ извне класса возможен.
  • Пример:

    
    class ApiClient:
    def __init__(self):
        self._base_url = "https://api.example.com"  # Защищенный атрибут
        self._session = requests.Session()
    
    def _make_request(self, endpoint):  # Защищенный метод
        return self._session.get(self._base_url + endpoint)

Доступ все равно возможен, но это не рекомендуется

client = ApiClient() print(client._base_url) # Работает, но нарушает соглашение


### Двойное подчеркивание (`__name`)
*   **Семантика:** Вызывает механизм **name mangling** (искажение имени). Цель — избежать случайных конфликтов имен в подклассах, а не обеспечить приватность.
*   **Поведение:** Интерпретатор изменяет имя атрибута внутри класса на `_ClassName__attribute`. Это делает доступ извне менее очевидным, но не невозможным.
*   **Пример:**
```python
class MyClass:
    def __init__(self):
        self.__private_value = 42  # Имя будет искажено

    def __private_method(self):    # Имя будет искажено
        return "secret"

obj = MyClass()
# Прямой доступ не сработает
# print(obj.__private_value)  # AttributeError

# Но доступ через искаженное имя возможен
print(obj._MyClass__private_value)  # Выведет 42
print(obj._MyClass__private_method())  # Выведет 'secret'

Для тестировщика (QA): При написании модульных или интеграционных тестов на Python:

  1. Обычно тестируют только публичный интерфейс (методы без подчеркиваний).
  2. Если необходимо протестировать внутреннюю логику, обращаются к защищенным (_) методам, осознавая хрупкость таких тестов.
  3. К методам с двойным подчеркиванием (__) обращаться напрямую в тестах крайне не рекомендуется — это нарушает инкапсуляцию, задуманную разработчиком, и такие тесты будут ломаться при любом рефакторинге.

Ответ 18+ 🔞

А, слушай, вот эта тема с подчёркиваниями в Python — она у новичков постоянно мозги выносит. Все думают, что это какая-то магическая защита, как в других языках. А на деле — чистой воды договорняк, ёпта.

Смотри, есть у нас один подчёрк, типа _name. Это такой вежливый намёк, типа «чувак, не лезь сюда, если не шаришь». Никаких замков, никаких блоков. Просто разработчик тебе как бы кивает: «Это для внутренних дел, окей?». А ты берёшь и лезешь. И оно работает! Потому что Python на доверии живёт, доверия ебать ноль, но так уж заведено.

class ApiClient:
    def __init__(self):
        self._base_url = "https://api.example.com"  # Типа, не трогай
        self._session = requests.Session()

    def _make_request(self, endpoint):  # Внутренняя кухня
        return self._session.get(self._base_url + endpoint)

# А ты берёшь и трогаешь
client = ApiClient()
print(client._base_url)  # И всё работает! Но ты же мудак после этого.

А вот два подчёрка — это уже поинтереснее. __name. Тут уже не просто намёк, а реальный механизм, который называется name mangling. Искажение имени, бля. Интерпретатор такой: «Ага, два подчёрка? Ща я тебе имя так склею, что твоя собственная бабушка не узнает». Он приписывает спереди _ИмяКласса. Получается _MyClass__private_value. Это не для приватности, а чтобы в дочерних классах случайно не перекрыть атрибут таким же именем. Хитрая жопа, да.

class MyClass:
    def __init__(self):
        self.__private_value = 42  # Щас его исковеркаем

    def __private_method(self):    # И эту тоже
        return "secret"

obj = MyClass()
# Прямой доступ — облом
# print(obj.__private_value)  # AttributeError — нихуя не найдено

# Но если ты упоротый и знаешь пароль...
print(obj._MyClass__private_value)  # Во, 42, на тебе!
print(obj._MyClass__private_method())  # 'secret', доволен?

А теперь, если ты тестировщик (QA), запомни раз и навсегда:

  1. Тестируй только то, что наружу торчит. Методы без подчёркиваний — твои лучшие друзья. Всё остальное — не твоя собака.
  2. Если приперло и надо залезть в кишки (_method), то делай это с осознанием, что завтра разработчик может всё переписать, и твои тесты накроются медным тазом. Ты сам потом будешь охуевать.
  3. К двойным подчёркам (__) даже не думай лезть в нормальных тестах. Это как вскрывать сейф отвёрткой — можно, но зачем? Ты сломаешь всю задумку, и при первом же рефакторинге у тебя будет овердохуища работы по починке. Просто не надо.