Свойства (property) в Python появились как способ элегантно реализовывать инкапсуляцию атрибутов, аналогично геттерам и сеттерам из других языков (Java/C++), но без необходимости явно вызывать методы. До property приходилось реализовывать доступ к переменным через явные методы get/set, что усложняло и засоряло интерфейс класса.
Проблема состоит в том, чтобы у пользователя класса был прозрачный интерфейс работы с атрибутами (используя dot-нотацию obj.x), а под капотом можно было бы контролировать логику вычисления, проверки, кэширования или валидации значений. Без property при изменении внутренней реализации приходится менять все вызовы, что приводит к массовым ошибкам и снижению расширяемости.
Решение — декоратор @property позволяет превратить метод в атрибут, и заодно скрыть логику вычисления, проверки или ленивая загрузка внутри методов, не меняя внешний интерфейс класса. Геттер реализует только для чтения, с помощью .setter организуют запись, а .deleter — удаление.
Пример кода:
class Rectangle: def __init__(self, width, height): self._width = width self._height = height @property def area(self): # 'area' теперь можно читать как атрибут return self._width * self._height @property def width(self): return self._width @width.setter def width(self, value): # автоматически вызывается при присваивании rect.width = ... assert value > 0, "Width must be positive" self._width = value rect = Rectangle(3, 4) print(rect.area) # 12 rect.width = 10 print(rect.area) # 40
Ключевые особенности:
Может ли property работать с класс-методами или статическими методами?
Нет. property делает только instance-level (экземпляров) свойства. Для class-level используйте специальные дескрипторы или @classmethod-property (реализуется вручную).
Если объявить property только с getter без setter, можно ли будет записать в атрибут?
Нет. Такой property read-only; попытка присваивания вызовет AttributeError.
Что будет, если внутри setter возникнет исключение (например, assert)?
Исключение поднимется наружу, присваивание не произойдет, а значение атрибута останется прежним. Это часто используют для валидации.
Негативный кейс: Публичные атрибуты класса, изменение их без контроля.
Плюсы: быстро, просто.
Минусы: нельзя изменить внутреннюю логику без переписывания кода клиента, возможны несогласованные состояния.
Положительный кейс: Инкапсуляция через property, логика в getter/setter, строгие проверки.
Плюсы: гибкость, контроль, прозрачность, безопасная эволюция API.
Минусы: немного больше кода, незначительное усложнение при отладке.