Глава 14 · Создаём объекты реального мира
Инкапсуляция
Атрибуты доступны напрямую — и это может сломать состояние объекта. Разбираемся, как этого избежать.
Проблема: атрибуты доступны напрямую
Ничто не мешает изменить атрибут объекта в обход всех методов — напрямую, снаружи класса:
Debug Lab 5: прямое присваивание ломает состояние объекта
slomannoe_zdorove.py
anna = Player("Anna")
anna.health = -50 # напрямую, в обход take_damage()
print(anna.health)
>>> print(anna.health)
-50
Метод take_damage() аккуратно не даёт health уйти ниже нуля — но НИЧТО не заставляет пользоваться именно этим методом. Присваивание anna.health = -50 обходит всю защитную логику напрямую, и объект оказывается в состоянии, которое сам класс считал невозможным.
Исправленный код
cherez_metod.py
anna.take_damage(150) # health корректно останавливается на 0
print(anna.health)
Инкапсуляция — идея хранить состояние объекта «внутри» и разрешать менять его только через методы, которые могут проверить, что новое значение осмысленно.
Соглашение об именах: _internal и __name
| Запись | Что означает по соглашению |
|---|---|
name | публичный атрибут — пользуйтесь снаружи свободно |
_name | «внутреннее» — не трогайте снаружи, хотя технически доступ есть |
__name | включает подмену имени (name mangling) — доступ снаружи усложнён, но не исчезает |
dvojnoe_podcherkivanie.py
class Konto:
def __init__(self, balans):
self.__balans = balans
schet = Konto(100)
print(schet._Konto__balans) # 100 — доступ ЕСТЬ, просто имя изменено
Частое заблуждение: «__private по-настоящему приватно»
Это не так — в Python нет настоящей приватности на уровне языка.
__balans автоматически переименовывается в _Konto__balans (name mangling) — это защищает в основном от СЛУЧАЙНОГО совпадения имён при наследовании, а не от намеренного доступа снаружи. Инкапсуляция в Python — это соглашение и дисциплина команды, а не запрет со стороны интерпретатора.Практика: инкапсуляция
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки