Декоратор property в Python

Содержание
Введение
Предпосылки
Пример
setter
deleter
Полный код примера
Похожие статьи

Введение

Это продолжение статьи «Классы» из раздела «ООП в Python» .

Для лучшего понимания этого материала пригодятся знания из следующих статей: Методы , Класс методы , Статические методы , super() , Декораторы , isinstance()

Партнёром этой статьи будем считать моего хостинг-провайдера beget.com

Предпосылки

Рассмотрим простой класс

class Employee: def __init__(self, first, last): self.first = first self.last = last self.email = first + '.' + last + '@beget.com' def fullname(self): return f'{self.first} {self.last}' emp_1 = Employee("Ivan", "Petrov") print(emp_1.first) print(emp_1.email) print(emp_1.fullname())

python property_deco.py

Ivan Ivan.Petrov@beget.com Ivan Petrov

Изменим только атрибут first у emp_1 и посмотрим как преобразится вывод

class Employee: def __init__(self, first, last): self.first = first self.last = last self.email = first + '.' + last + '@beget.com' def fullname(self): return f'{self.first} {self.last}' emp_1 = Employee("Ivan", "Petrov") # Change the attribute emp_1.first = 'Andrei' print(emp_1.first) print(emp_1.email) print(emp_1.fullname())

python property_deco.py

Andrei Ivan.Petrov@beget.com Andrei Petrov

Как видите, email остался прежним, как-будто работника по-прежнему зовут Иван. Это атрибут был создан вместе с объектом и больше его никто не трогал.

fullname обновился, так как этот метод каждый раз переиспользует текущие атрибуты.

Что делать если нужно автоматически обновлять email?

Если убрать атрибут email и создать вместо него метод email по аналогии с fullname это заработает, но все, кто пользовался этим классом должны будут изменить свой код. Это нарушает обратную совместимость.

Обратите внимание на вызов метода - нужно везде добавить ()

class Employee: def __init__(self, first, last): self.first = first self.last = last # self.email = first + "." + last + "@beget.com" def fullname(self): return f"{self.first} {self.last}" def email(self): return f"{self.first}.{self.last}@beget.com" emp_1 = Employee("Ivan", "Petrov") # Change the attribute emp_1.first = "Andrei" print(emp_1.first) print(emp_1.email()) print(emp_1.fullname())

python property_deco.py

Andrei Andrei.Petrov@beget.com Andrei Petrov

Оставить и метод и атрибут с тем же название нельзя - получим ошибку TypeError: 'str' object is not callable

Andrei Traceback (most recent call last): File "/home/andrei/python/property_deco.py", line 21, in <module> print(emp_1.email()) TypeError: 'str' object is not callable

Пример

Если написать метод email() и добавить к нему декоратор @property обратная совместимость не пострадает.

class Employee: def __init__(self, first, last): self.first = first self.last = last def fullname(self): return f"{self.first} {self.last}" @property def email(self): return f"{self.first}.{self.last}@beget.com" emp_1 = Employee("Ivan", "Petrov") # Change the attribute emp_1.first = "Andrei" print(emp_1.first) print(emp_1.email) print(emp_1.fullname())

python property_deco.py

Andrei Andrei.Petrov@beget.com Andrei Petrov

РЕКЛАМА от Google. Может быть недоступна в вашем регионе.

Конец рекламы от Google. Если в блоке пусто считайте это рекламой моей телеги

setter

Добавим декоратор @property к обоим методам и попробуем задать fullname

class Employee: def __init__(self, first, last): self.first = first self.last = last @property def fullname(self): return f"{self.first} {self.last}" @property def email(self): return f"{self.first}.{self.last}@beget.com" emp_1 = Employee("Ivan", "Petrov") # Change the attribute emp_1.fullname = "Andrei Olegovich" print(emp_1.first) print(emp_1.email) print(emp_1.fullname)

python property_deco.py

Traceback (most recent call last): File "/home/andrei/python/property_deco.py", line 21, in <module> emp_1.fullname = "Andrei Olegovich" AttributeError: can't set attribute

Избавиться от ошибки поможет декоратор setter

@fullname.setter def fullname(self, name): first, last = name.split(' ') self.first = first self.last = last emp_1 = Employee("Ivan", "Petrov") # Change the attribute emp_1.fullname = "Andrei Olegovich" print(emp_1.first) print(emp_1.email) print(emp_1.fullname)

python property_deco.py

Andrei Andrei.Petrov@beget.com Andrei Petrov

РЕКЛАМА от Яндекса. Может быть недоступна в вашем регионе

Конец рекламы от Яндекса. Если в блоке пусто считайте это рекламой моей телеги

deleter

Удалить атрибут лучше всего с помощью декоратора deleter

@fullname.deleter def fullname(self): print("Delete Name!") self.first = None self.last = None emp_1.fullname = "Andrei Olegovich" print(emp_1.first) print(emp_1.email) print(emp_1.fullname) del emp_1.fullname print(emp_1.fullname)

python property_deco.py

Andrei Andrei.Olegovich@beget.com Andrei Olegovich Delete Name! None None

РЕКЛАМА от Яндекса. Может быть недоступна в вашем регионе

Конец рекламы от Яндекса. Если в блоке пусто считайте это рекламой моей телеги

Полный код примера

class Employee: def __init__(self, first, last): self.first = first self.last = last @property def email(self): return f"{self.first}.{self.last}@beget.com" @property def fullname(self): return f"{self.first} {self.last}" @fullname.setter def fullname(self, name): first, last = name.split(' ') self.first = first self.last = last @fullname.deleter def fullname(self): print("Delete Name!") self.first = None self.last = None emp_1 = Employee("Ivan", "Petrov") # Change the attribute emp_1.fullname = "Andrei Olegovich" print(emp_1.first) print(emp_1.email) print(emp_1.fullname) del emp_1.fullname print(emp_1.fullname)

Похожие статьи
ООП в Python
Классы
Методы
class variables
class methods
Статические методы
Наследование
Специальные методы
dataclass
__slots__
Декоратор property
super()

РЕКЛАМА хостинга Beget, которым я пользуюсь более десяти лет

Изображение баннера

Конец рекламы хостинга Beget, который я всем рекомендую.

Поиск по сайту

Подпишитесь на Telegram канал @aofeed чтобы следить за выходом новых статей и обновлением старых

Перейти на канал

@aofeed

Задать вопрос в Телеграм-группе

@aofeedchat

Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@urn.su если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящую по тематике.
3. Реклама на моём сайте имеет максимальный уровень цензуры. Если Вы увидели рекламный блок недопустимый для просмотра детьми школьного возраста, вызывающий шок или вводящий в заблуждение - пожалуйста свяжитесь с нами по электронной почте
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......
5. Статьи можно расшарить в соцсетях, нажав на иконку сети: