← Назад к вопросам

Как обозначаются приватные данные и методы в Python?

1.2 Junior🔥 221 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как обозначаются приватные данные и методы в Python?

В Python нет настоящих приватных атрибутов как в Java или C++. Вместо этого используются соглашения и механизмы, которые сигнализируют о намерении разработчика.

1. Одиночное подчеркивание (_) — соглашение о внутренних членах

Одиночное подчеркивание в начале означает, что это внутренний (private по соглашению) атрибут:

class User:
    def __init__(self, name, password):
        self.name = name  # Публичный
        self._password = password  # Приватный по соглашению
        self._created_at = datetime.now()  # Приватный
    
    def _validate_password(self):  # Приватный метод
        return len(self._password) >= 8
    
    def set_password(self, new_password):
        if self._validate_password():
            self._password = new_password

user = User("Alice", "secret123")
print(user.name)  # OK
print(user._password)  # Technически OK, но нарушаем соглашение

2. Двойное подчеркивание (__) — name mangling

Двойное подчеркивание заставляет Python переименовать атрибут (name mangling):

class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # Приватный с name mangling
    
    def __verify_balance(self):  # Приватный метод
        return self.__balance > 0
    
    def withdraw(self, amount):
        if self.__verify_balance():
            self.__balance -= amount
            return True
        return False
    
    def get_balance(self):
        return self.__balance

account = BankAccount(1000)
print(account.get_balance())  # 1000

# Попытка прямого доступа
# print(account.__balance)  # AttributeError!

# Python переименовал атрибут (name mangling)
print(account._BankAccount__balance)  # 1000

3. Сравнение подходов

ВариантСинтаксисИспользование
ПубличныйnameAPI класса
Приватный (соглашение)_nameВнутреннее использование
Приватный (name mangling)__nameКритичные данные

4. Практические примеры

Пример 1: Соглашение о приватности

class Database:
    def __init__(self, url):
        self._connection = None  # Не трогай напрямую
        self._url = url
    
    def _connect(self):  # Внутренний метод
        pass
    
    def query(self, sql):
        if not self._connection:
            self._connect()
        return self._connection.execute(sql)

db = Database("postgresql://localhost")
# Правильно:
db.query("SELECT * FROM users")

Пример 2: Name mangling для критичных данных

class SecretKey:
    def __init__(self, key):
        self.__key = key  # Скрыто с name mangling
    
    def __validate_key(self):  # Приватный метод
        return True
    
    def use_key(self):
        if self.__validate_key():
            return self.__key
        raise ValueError("Invalid")

key = SecretKey("super_secret_token")
print(key.use_key())  # super_secret_token

5. Properties для контролируемого доступа

class Temperature:
    def __init__(self, celsius=0):
        self._celsius = celsius  # Приватный по соглашению
    
    @property
    def celsius(self):
        return self._celsius
    
    @property
    def fahrenheit(self):
        return self._celsius * 9/5 + 32
    
    @celsius.setter
    def celsius(self, value):
        if value < -273.15:
            raise ValueError("Невозможная температура")
        self._celsius = value

temp = Temperature(25)
print(temp.celsius)  # 25
print(temp.fahrenheit)  # 77.0

temp.celsius = 30  # Работает через setter с проверкой

6. Специальные методы (dunder methods)

class MyClass:
    def __init__(self):
        pass
    
    def __str__(self):
        return "MyClass instance"
    
    def __repr__(self):
        return "MyClass()"
    
    def __len__(self):
        return 42
    
    def __getitem__(self, key):
        return f"item {key}"
    
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        pass

obj = MyClass()
print(str(obj))  # MyClass instance
print(len(obj))  # 42

7. Лучшие практики

class GoodClass:
    def __init__(self, public_data, secret_data):
        # Публичные данные
        self.public_data = public_data
        
        # Приватные по соглашению (внутреннее использование)
        self._cache = None
        self._internal_state = {}
        
        # Критичные данные (name mangling)
        self.__secret = secret_data
    
    def get_data(self):
        # Публичный API
        if self._cache is None:
            self._cache = self._compute()
        return self._cache
    
    def _compute(self):
        # Внутренний метод (не трогать)
        return self.public_data * 2
    
    def __validate(self):
        # Совсем приватный метод
        return len(self.__secret) > 0

# Использование
obj = GoodClass("data", "secret")
print(obj.public_data)  # OK
print(obj.get_data())  # OK

8. Вывод

Используй правило:

  • name — публичный API
  • _name — внутренний (соглашение)
  • __name — критичное (name mangling)
  • @property — контролируемый доступ

Python выбрал гибкость и доверие разработчикам вместо строгого принуждения.