← Назад к вопросам
Для чего используется @property в Python?
2.0 Middle🔥 241 комментариев
#Python Core#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Декоратор @property в Python
@property — мощный инструмент для создания управляемых атрибутов класса. Он позволяет вызывать методы как свойства, сохраняя возможность добавить логику при доступе.
Основная идея
Без @property нужно было бы писать getters и setters как в Java:
# ❌ Плохо — verbose, не pythonic
class Person:
def __init__(self, age):
self._age = age
def get_age(self):
return self._age
def set_age(self, value):
if value < 0:
raise ValueError("Age cannot be negative")
self._age = value
person = Person(25)
print(person.get_age()) # Неудобно
person.set_age(26) # Неудобно
С @property код становится чище:
# ✅ Хорошо — pythonic, добавляем логику без изменения интерфейса
class Person:
def __init__(self, age):
self._age = age
@property
def age(self):
"""Getter для возраста"""
return self._age
@age.setter
def age(self, value):
"""Setter с валидацией"""
if value < 0:
raise ValueError("Age cannot be negative")
self._age = value
@age.deleter
def age(self):
"""Deleter если нужно удалить"""
del self._age
person = Person(25)
print(person.age) # 25 — выглядит как атрибут
person.age = 26 # Вызывает setter с валидацией
Основные преимущества
1. Изменение реализации без изменения API
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
self._celsius = value
@property
def fahrenheit(self):
"""Вычисляемое свойство"""
return self._celsius * 9/5 + 32
temp = Temperature(0)
print(temp.fahrenheit) # 32 — вычисляется на лету
temp.celsius = 100
print(temp.fahrenheit) # 212
Если завтра захотите добавить кэширование или логирование, это не потребует изменения кода, вызывающего температуру.
2. Валидация данных
class Rectangle:
def __init__(self, width, height):
self._width = width
self._height = height
@property
def width(self):
return self._width
@width.setter
def width(self, value):
if value <= 0:
raise ValueError("Width must be positive")
self._width = value
rect = Rectangle(10, 20)
rect.width = -5 # ❌ ValueError: Width must be positive
3. Computed properties (вычисляемые атрибуты)
class User:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@property
def full_name(self):
"""Автоматически создаётся из first и last name"""
return f"{self.first_name} {self.last_name}"
@full_name.setter
def full_name(self, value):
self.first_name, self.last_name = value.split()
user = User("John", "Doe")
print(user.full_name) # "John Doe"
user.full_name = "Jane Smith"
print(user.first_name) # "Jane"
4. Ленивая загрузка (lazy loading)
class DataSource:
def __init__(self, url):
self.url = url
self._data = None
@property
def data(self):
"""Загружаем данные только при первом доступе"""
if self._data is None:
print(f"Loading data from {self.url}...")
self._data = fetch_from_api(self.url) # Дорогая операция
return self._data
ds = DataSource("https://api.example.com/data")
# data не загружена
print(ds.data) # Загрузится здесь
print(ds.data) # Вернёт кэшированный результат
@property vs обычные методы
# @property — если это логичнее рассматривать как атрибут
user.full_name
# Метод — если это явно операция/действие
user.get_profile() # Загружает профиль с сервера
user.save() # Сохраняет в БД
Когда не использовать @property
# ❌ Плохо — дорогая операция скрыта
@property
def heavy_computation(self):
"""Вычисление занимает 10 секунд!"""
time.sleep(10)
return 42
# ✅ Лучше сделать явным методом
def compute_heavy(self):
"""Явно видно, что это дорогая операция"""
time.sleep(10)
return 42
Итог
@property в Python — инструмент для:
- Инкапсуляции с валидацией
- Вычисляемых атрибутов
- Ленивой загрузки данных
- Изменения реализации без изменения API
Это делает код более читаемым и гибким.