Выделите текст, нажмите 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
может пригодиться, если вы будете делать свои декораторы, реализующие какие-то особенные свойства.
Вам ответят команда поддержки Хекслета или другие студенты.
Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.
или войти в аккаунт
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.
Наши выпускники работают в компаниях:
Зарегистрируйтесь или войдите в свой аккаунт