Ответ
@property — это декоратор в Python, который позволяет превратить метод класса в атрибут, доступный только для чтения, и при этом легко добавить логику его вычисления или валидации при попытке установки значения. Это ключевой инструмент для реализации инкапсуляции и управления доступом к данным.
Как это работает: Декоратор создает property object, который использует методы-геттер, сеттер и делитер.
Базовый пример (вычисляемый атрибут):
class Circle:
def __init__(self, radius):
self._radius = radius # Приватный атрибут
@property
def radius(self):
"""Геттер. Вызывается при обращении к circle.radius"""
return self._radius
@property
def area(self):
"""Вычисляемое свойство. Площадь зависит от радиуса."""
return 3.14159 * self._radius ** 2
# Использование
c = Circle(5)
print(c.radius) # 5 -> Вызывается геттер radius
print(c.area) # 78.53975 -> Вызывается геттер area
# c.area = 10 # AttributeError: can't set attribute (у area нет сеттера)
Полный контроль с сеттером и делитером:
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
"""Сеттер. Позволяет добавить валидацию."""
if value < -273.15:
raise ValueError("Температура ниже абсолютного нуля!")
self._celsius = value
@property
def fahrenheit(self):
"""Еще одно вычисляемое свойство."""
return self._celsius * 9/5 + 32
@fahrenheit.setter
def fahrenheit(self, value):
"""Сеттер для свойства fahrenheit изменяет базовое значение celsius."""
self._celsius = (value - 32) * 5/9
# Использование
t = Temperature(25)
print(t.fahrenheit) # 77.0
t.fahrenheit = 100
print(t.celsius) # 37.777... -> celsius изменилось через сеттер fahrenheit
# t.celsius = -300 # ValueError: Температура ниже абсолютного нуля!
Зачем это нужно:
- Инкапсуляция: Позволяет скрыть внутреннее представление данных (например,
_radius), предоставив контролируемый публичный интерфейс. - Валидация: Сеттер позволяет проверять и отклонять некорректные значения.
- Вычисляемые атрибуты: Можно создавать атрибуты, которые вычисляются на лету на основе других данных.
- Обратная совместимость: Если ранее у класса был публичный атрибут
x, и вы решили добавить логику при его изменении, вы можете превратить его в property, не ломая существующий код, который используетobj.x.