Объяснение к уроку
@propertyПосле этого урока ты сможешь:
@property.В Python поля private в стиле Java не используются напрямую. Имя вроде _balance указывает на внутреннее использование по соглашению; это не жесткая защита доступа. Свойство позволяет внешнему коду читать account.balance, в то время как метод «под капотом» вычисляет или валидирует это значение.
Определи геттер с помощью декоратора @property. Для доступных для записи свойств добавь сеттер с помощью @property_name.setter. Внутри сеттера выполняй запись в базовое поле (self._balance), а не в само имя свойства (self.balance), иначе сеттер будет бесконечно вызывать сам себя.
Свойство также может быть доступным только для чтения: для этого просто опусти сеттер. Вычисляемые свойства должны согласовываться с текущим состоянием объекта. Используй свойства для осмысленной валидации или вычислений, а не просто для копирования многословных геттеров и сеттеров из Java.
_status хранит значение, а status предоставляет чистый интерфейс для чтения.
class Task:
def __init__(self, status):
self._status = status
@property
def status(self):
return self._status
print(Task("queued").status)Вывод:
queuedСеттер отклоняет отрицательные значения, сохраняя прежний показатель.
class Counter:
def __init__(self, value):
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, next_value):
if next_value >= 0:
self._value = next_value
counter = Counter(3)
counter.value = -8
print(counter.value)Вывод:
3Нет необходимости синхронизировать отдельное поле remaining.
class Quota:
def __init__(self, limit, used):
self.limit = limit
self.used = used
@property
def remaining(self):
return self.limit - self.used
quota = Quota(100, 35)
print(quota.remaining)Вывод:
65Используй доступ через точку без круглых скобок; геттер свойства выполняется автоматически.
class Release:
def __init__(self, passed):
self.passed = passed
@property
def ready(self):
return self.passed > 0
release = Release(2)
print(f"Ready: {release.ready}")Вывод:
Ready: True| Потребность | Решение |
|---|---|
| Соглашение о внутреннем поле | self._value |
| Публичный доступ на чтение | Геттер @property |
| Валидируемый доступ на запись | @value.setter |
| Вычисляемое значение | Свойство только для чтения без сеттера |
| Избежать рекурсивного сеттера | Присваивать базовое поле, а не self.value |
obj.total()) вместо обычного чтения (obj.total).self.value = ... внутри сеттера для value._value защищено от внешнего доступа; это лишь соглашение.