🔖 Справочник: инкапсуляция
⚡ Кратко
Используйте эту страницу как шпаргалку: найдите нужную конструкцию, сравните синтаксис с примером и затем примените её в своём коде.
Соглашения об именовании
| Имя | Уровень доступа | Назначение |
|---|---|---|
name |
Публичный | Открытый интерфейс, доступен отовсюду. |
_name |
Защищённый | Внутреннее использование, доступен в наследниках. |
__name |
Приватный | Строго внутреннее, манглируется в _ClassName__name. |
Геттер и сеттер вручную
class Temperature:
def __init__(self) -> None:
self.__celsius = 0
def get_celsius(self) -> float:
return self.__celsius
def set_celsius(self, value: float) -> None:
if value < -273.15:
raise ValueError("Слишком низкая температура")
self.__celsius = value
Свойство через @property
class Temperature:
def __init__(self, value: float) -> None:
self.__celsius = 0
self.celsius = value
@property
def celsius(self) -> float:
return self.__celsius
@celsius.setter
def celsius(self, value: float) -> None:
if value < -273.15:
raise ValueError("Слишком низкая температура")
self.__celsius = value
Только для чтения
class Circle:
def __init__(self, radius: float) -> None:
self.__radius = radius
@property
def radius(self) -> float:
return self.__radius
@property
def area(self) -> float:
return 3.14159 * self.__radius ** 2
Свойство без сеттера нельзя изменить извне.
Дескриптор: методы протокола
| Метод | Когда вызывается | Аргументы |
|---|---|---|
__set_name__(self, owner, name) |
При создании класса, где объявлен дескриптор | owner — класс, name — имя атрибута |
__get__(self, instance, owner) |
Чтение атрибута: obj.attr |
instance — объект (None при доступе через класс) |
__set__(self, instance, value) |
Запись: obj.attr = value |
value — присваиваемое значение |
__delete__(self, instance) |
Удаление: del obj.attr |
— |
Универсальный дескриптор-валидатор
class PositiveNumber:
def __set_name__(self, owner, name: str) -> None:
self.private_name = "_" + name
def __get__(self, instance, owner):
if instance is None:
return self
return getattr(instance, self.private_name)
def __set__(self, instance, value: float) -> None:
if value < 0:
raise ValueError("Значение не может быть отрицательным")
setattr(instance, self.private_name, value)
def __delete__(self, instance) -> None:
delattr(instance, self.private_name)
class Person:
age = PositiveNumber()
balance = PositiveNumber()
def __init__(self, age: int, balance: float = 0) -> None:
self.age = age
self.balance = balance
Значение хранится под именем _age / _balance; обращение идёт по именам age и balance.
Приватный метод
class User:
def __init__(self, name: str) -> None:
self.name = name
self.__id = self.__generate_id()
def __generate_id(self) -> str:
return f"user-{id(self)}"
Проверка принадлежности к классу
| Функция/атрибут | Назначение |
|---|---|
obj.__dict__ |
Словарь атрибутов объекта, включая манглированные имена. |
Class.__mro__ |
Порядок разрешения методов (менее связан, но полезен в сочетании). |