Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос нашим менторам. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Свойства

Свойства

Представим, что у нас есть такой класс:

class Person:
    def __init__(self, name, surname):
        self.name = name
        self.surname = surname

Что нам делать, если мы захотим иметь возможность получить ещё и полное имя (имя+фамилию) объекта?

Мы могли бы в инициализаторе добавить строчку self.full_name = name + ' ' + surname. Но если впоследствии имя или фамилия поменяются, полное имя устареет, и его нужно будет не забыть поменять.

Также мы могли бы добавить метод с именем вроде get_full_name, который бы возвращал полное имя. Но и такой вариант не идеален, ведь нам хочется работать с полным именем, как с простым атрибутом-переменной!

Оказывается, что в Python есть средство, позволяющее получить атрибут, значение которого вычисляется динамически, то есть во время обращения к атрибуту. Речь идёт о свойствах.

Добавим в класс свойство и посмотрим на его использование:

>>> class Person:
...     def __init__(self, name, surname):
...         self.name = name
...         self.surname = surname
...     @property
...     def full_name(self):
...         return self.name + ' ' + self.surname
...
>>> tom = Person('Thomas', 'Smith')
>>> tom.full_name
'Thomas Smith'

full_name выглядит как утка, то есть как атрибут! Но вычисляется динамически. И если мы поменяем name, то full_name также изменится:

>>> tom.name = 'Alice'
>>> tom.full_name
'Alice Smith'

Как вы можете видеть, свойство объявляется как метод без параметров (кроме self, естественно), декорированный с помощью property. Такой метод, возвращающий динамически вычисляемое значение, называется геттером (getter).

Сеттер

Атрибутам пространства имён можно присваивать значения, но что делать, если атрибут — свойство? Если вы попытаетесь присвоить значение свойству имеющему один лишь getter, вы получите ошибку "AttributeError: can't set attribute".

Чтобы иметь возможность присвоить значение свойству, нужно использовать сеттер (setter). Сеттер — это тоже метод, который принимает новое значение для атрибута и как-то его обрабатывает. Чтобы метод стал сеттером, его тоже нужно соответствующим образом декорировать. Если у вас уже есть геттер, вы можете сделать так:

class Person:
    def __init__(self, name, surname):
        self.name = name
        self.surname = surname

    @property
    def full_name(self):
        return self.name + ' ' + self.surname

    # сеттер для свойства full_name
    @full_name.setter
    def full_name(self, new):
        self.name, self.surname = new.split(' ')

Теперь свойству full_name можно присваивать новое полное имя, которое в итоге будет разделено по пробелу на две части, первая из которых станет новым именем, а вторая — фамилией. Пример:

>>> tom = Person('Thomas', 'Smith')
>>> tom.full_name
'Thomas Smith'
>>> tom.full_name = 'Alice Cooper'
>>> tom.name
'Alice'
>>> tom.surname
'Cooper'

Сеттеры часто используют для того, чтобы проверить корректность нового значения или произвести какие-то его преобразования перед фактическим сохранением в другие атрибуты.

Делитер

Похожим на объявление сеттера образом объявляется и делитер (deleter). Этот метод вызывается тогда, когда происходит отбрасывание старого значения свойства, например — при присваивании свойству нового значения. Deleter позволяет напоследок сделать что-то необходимое, например, закрыть открытый ранее файл или сетевое соединение, словом, "прибрать за собой".

Не то чтобы делитеры часто приходится объявлять явно, ведь Python и сам неплохо справляется с закрытием тех же файлов, когда файловые объекты перестают быть нужны и уничтожаются сборщиком мусора. Но о самой возможности знать стоит, поэтому я её и описал.

Декоратор property

Если посмотреть в документацию к декоратору property, то можно увидеть такую сигнатуру:

property(fget=None, fset=None, fdel=None, doc=None)

Первые три аргумента позволяют задать getter, setter и deleter, а аргумент doc позволяет указать docstring. В такой форме property удобно использовать, когда вы уже имеете готовые функции, которые хотите просто "упаковать" в свойство:

def get_full_name(self):
    ...

def set_full_name(self, new):
    ...

class Person:
    ...
    full_name = property(
        fget=get_full_name,
        fset=set_full_name,
        doc='A full name of person'
    )

Также обычный вызов property может пригодиться, если вы будете делать свои декораторы, реализующие какие-то особенные свойства.


<span class="translation_missing" title="translation missing: ru.web.courses.lessons.mentors.mentor_avatars">Mentor Avatars</span>

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят менторы из команды Хекслета или другие студенты.

Для полного доступа к курсу, нужна профессиональная подписка

Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, даст возможность обращаться за помощью к менторам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
115
курсов
892
упражнения
2241
час теории
3196
тестов

Зарегистрироваться

или войти в аккаунт

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг».

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг».