← Назад к вопросам
Как обозначаются приватные данные и методы в 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. Сравнение подходов
| Вариант | Синтаксис | Использование |
|---|---|---|
| Публичный | name | API класса |
| Приватный (соглашение) | _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 выбрал гибкость и доверие разработчикам вместо строгого принуждения.