Ответ
В Python инкапсуляция — это в первую очередь соглашение, а не строгое правило, как в Java или C++. Она реализуется с помощью следующих механизмов:
-
Соглашения об именовании (префиксы
_и__):- Одинарное подчеркивание (
_): Сигнализирует, что атрибут или метод является защищенным (protected) и предназначен для внутреннего использования в классе или его наследниках. Технически доступ к нему не ограничен.class MyClass: def __init__(self): self._internal_var = 10 -
Двойное подчеркивание (
__): Делает атрибут или метод приватным (private) с помощью механизма Name Mangling. Python изменяет имя атрибута, добавляя к нему имя класса (_ClassName__attribute), что затрудняет случайный доступ извне.class MyClass: def __init__(self): self.__private_var = 20 obj = MyClass() # print(obj.__private_var) # AttributeError print(obj._MyClass__private_var) # Так доступ возможен
- Одинарное подчеркивание (
-
Свойства (
@property): Декоратор@propertyпозволяет управлять доступом к атрибутам класса, превращая методы в атрибуты, доступные только для чтения. С помощью декораторов@<name>.setterи@<name>.deleterможно добавить логику для записи и удаления, например, для валидации данных.Пример с валидацией:
class BankAccount: def __init__(self, initial_balance): if initial_balance < 0: raise ValueError("Начальный баланс не может быть отрицательным") self.__balance = initial_balance @property def balance(self): """Геттер для получения баланса.""" return self.__balance @balance.setter def balance(self, value): """Сеттер с валидацией для изменения баланса.""" if value < 0: raise ValueError("Баланс не может быть отрицательным") self.__balance = value account = BankAccount(100) print(account.balance) # 100 (работает геттер) account.balance = 200 # OK (работает сеттер) # account.balance = -50 # Вызовет ValueErrorТакой подход позволяет скрыть внутреннюю реализацию (
__balance) и предоставить безопасный публичный интерфейс (balance).