Перейти к содержанию

232 уроков, 16 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 6 из 20 Средний 35 мин 130 XP

@property: вычисляемые атрибуты

@property превращает метод в атрибут без скобок: площадь пересчитывается сама, сеттер проверяет данные. Разбираем, когда свойство излишне.

Редакция Питоники

В уроке про инкапсуляцию баланс прятался за методами get_balance() и deposit(). Схема рабочая, но многословная: чтение — метод со скобками, запись — другой метод. В Python есть путь элегантнее: @property превращает метод в атрибут, который вычисляется при обращении, а его напарник-сеттер перехватывает присваивание. Снаружи — обычное поле, внутри — код с проверками.

Свойство: метод без скобок

Декоратор @property навешивается на метод без параметров, кроме self, — и его значение читается как атрибут: rect.area вместо rect.area(). Свойство удобно для вычисляемых полей: площадь из сторон, полное имя из имени и фамилии, возраст из даты рождения. Хранить их отдельно не стоит — легко рассинхронизировать; свойство пересчитывается при каждом обращении и потому не врёт. Свойство выглядит как поле, а работает как код: обращение к rect.area выполняет вычисление заново.

площадь без хранения
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    @property
    def area(self):
        return self.width * self.height

rect = Rectangle(4, 5)
print(rect.area)

rect.width = 10
print(rect.area)
Вывод
20
50
вычисляемое полное имя
class Person:
    def __init__(self, first, last):
        self.first = first
        self.last = last

    @property
    def full_name(self):
        return f"{self.first} {self.last}"

author = Person("Лев", "Толстой")
print(author.full_name)
Вывод
Лев Толстой

Сеттер: присваивание с проверкой

Свойство без сеттера только читается: попытка rect.area = 100 упадёт с AttributeError — и это хорошо: площадь не должна назначаться извне. Для перезаписываемых полей добавляется сеттер: @celsius.setter перехватывает присваивание t.celsius = ... и решает, принимать ли значение. Внутри сеттера живёт валидация — данные не попадают в объект некорректными.

температура не опускается ниже физики
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:
            print("Ниже абсолютного нуля не бывает")
            return
        self._celsius = value

t = Temperature(25)
print(t.celsius)

t.celsius = -300
t.celsius = -30
print(t.celsius)
Вывод
25
Ниже абсолютного нуля не бывает
-30
ЗадачаМетоды в стиле get/setС property
получить площадьrect.get_area()rect.area
записать с проверкойrect.set_width(10)rect.width = 10
вычисляемое полеметод со скобкамиатрибут без скобок
смена реализацииинтерфейс держится на методахполе заменяется свойством незаметно

Свойства завершают картину инкапсуляции: данные спрятаны в _полях, а наружу смотрят проверяемые атрибуты. Дальше: наследование — потомки расширяют классы через super(); super() и MRO — как Python ищет метод в иерархии. В финальном проекте курса property примет на себя все проверки.

Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

class Square:
    def __init__(self, side):
        self.side = side

    @property
    def perimeter(self):
        return self.side * 4

sq = Square(3)
sq.side = 10
print(sq.perimeter)
class Person:
    def __init__(self, first, last):
        self.first = first
        self.last = last

    @property
    def initials(self):
        return f"{self.first[0]}.{self.last[0]}."

p = Person("Агния", "Барто")
print(p.initials)
class Age:
    def __init__(self, value):
        self.value = value

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, new):
        self._value = max(new, 0)

age = Age(30)
age.value = -5
print(age.value)
Проверь себя
0 / 6

1. Как прочитать свойство area?

2. Зачем нужен @x.setter?

3. Когда вычисляется свойство area = width * height?

4. Почему в сеттере пишут self._celsius, а не self.celsius?

5. Что произойдёт при присваивании свойству без сеттера?

6. Когда property не нужен?

Карточки терминов
Запомнено: 0 / 6
Практика

Создайте класс Cube (куб): __init__ принимает side. Добавьте сеттер для side, отвергающий неположительные значения (печатает «Ребро должно быть положительным» и не меняет поле), и свойство surface, возвращающее площадь поверхности как 6 * side ** 2. Создайте куб с ребром 3 и выведите площадь, попробуйте задать side = -2, затем задайте side = 5 и снова выведите площадь.

practice.py
Вопросы и ответы по уроку

Что делает @property в Python?

Превращает метод в свойство: значение вычисляется при каждом обращении, но читается как атрибут, без скобок — rect.area вместо rect.area(). Используется для вычисляемых полей и для подмены простого атрибута логикой без смены интерфейса.

Как сделать атрибут «только для чтения»?

Объявите @property без парного сеттера: чтение работает, присваивание падает с AttributeError. Так поступают с производными значениями вроде площади — их нельзя назначить извне, потому что они зависят от других полей.

Чем property лучше методов get_area() и set_width()?

Интерфейсом: obj.area читается как поле, obj.width = 10 — как присваивание. Код вызывающей стороны не меняется, даже если внутри вы замените простое поле вычислением или добавите валидацию. Пары методов get/set в стиле Java в Python считаются шумом.

Урок 5: инкапсуляция

Почему property хранит данные в _celsius, а не в celsius?

Потому что имена свойства и закрытого поля должны различаться: запись self.celsius = value внутри сеттера celsius снова вызовет тот же сеттер — бесконечную рекурсию и RecursionError. Договорённость: публичное имя — свойство, _имя — место хранения.

Понравился урок? Сошлитесь на него

«Свойство выглядит как поле, а работает как код: обращение к rect.area выполняет вычисление заново.»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.