Декоратор @property() в Python
avatar
7 | (offline)
❤️‍🔥Notehunter Developer
Добавлено:
Категория: Основы «Python»
Комментариев: 0

Property в Python

Что такое property()? Функция используется для определения свойств в классах. Метод property() обеспечивает интерфейс для атрибутов экземпляра класса.

Он инкапсулирует атрибуты экземпляров и предоставляет свойства, аналогично тому, как это работает в Java и C#. Метод property() принимает на вход методы get, set и delete, и возвращает объекты класса property.

Давайте рассмотрим простой код без Property на примере класса, принимающего имя и возраст.

class Person:

    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def get_age(self):
        return self.__age

    def set_age(self, age):
        self.__age = age

Мы создали приватные age и name, и давайте попробуем задать значения и вывести в консоль

p = Person('Владислав', 23)
p.set_age(24)

print(p.get_age())

Получаем результат:

C:\Users\Razilator\Desktop\Courses\nth-coding\venv\Scripts\python.exe C:/Users/Razilator/Desktop/Courses/nth-coding/main.py
24

Process finished with exit code 0

Как видим, мы задали set_age 24 и его получили. А теперь представьте, что для каждой такой инициализации придется писать set_age много раз для многих других персон. Поэтому приходит к нам на помощь свойства Property

У нас есть ведь два метода, верно? Давайте сделаем следующее:

class Person:

    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def get_age(self):
        return self.__age

    def set_age(self, age):
        self.__age = age

    age = property(get_age, set_age)

В этом случае, нам не нужно запоминать постоянно имена наших геттеров и сеттеров, мы можем спокойно напрямую в приватные атрибуты задавать значения таким образом:

p = Person('Владислав', 23)
p.age = 24

print(p.age)

Результат:

C:\Users\Razilator\Desktop\Courses\nth-coding\venv\Scripts\python.exe C:/Users/Razilator/Desktop/Courses/nth-coding/main.py
24

Process finished with exit code 0

Как видите, мы можем присвоить p.age = 24, это отработает наш set_age, а можем вывести, без скобок p.age - это отработает наш get_age с помощью Property. К тому же, приоритет такого атрибута намного выше, чем у любого локального свойства, которое может присутствовать в экземпляре класса, даже с таким же названием свойства.

Можно сделать ещё следующим образом:

class Person:

    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    @property
    def get_age(self):
        return self.__age

    @get_age.setter
    def get_age(self, age):
        self.__age = age


p = Person('Владислав', 23)
p.get_age = 24

print(p.__dict__)

У Property есть свои декораторы, а именно getter, setter, deleter. Мы можем сделать такой единый удобный интерфейс. 

А давайте сделаем приближенно к первому варианту:

class Person:

    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age):
        self.__age = age


p = Person('Владислав', 23)
p.age = 24

print(p.__dict__)

Результат:

C:\Users\Razilator\Desktop\Courses\nth-coding\venv\Scripts\python.exe C:/Users/Razilator/Desktop/Courses/nth-coding/main.py
{'_Person__name': 'Владислав', '_Person__age': 24}

Process finished with exit code 0

Таким образом, мы избавились от функционального дублирования. 

Давайте ещё добавим deleter:


class Person:

    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age):
        self.__age = age

    @age.deleter
    def age(self):
        del self.__age


p = Person('Владислав', 23)
del p.age

print(p.age, p.__dict__)

И так как у нас не будет приватного атрибута age, мы получим ошибку:

C:\Users\Razilator\Desktop\Courses\nth-coding\venv\Scripts\python.exe C:/Users/Razilator/Desktop/Courses/nth-coding/main.py
Traceback (most recent call last):
  File "C:\Users\Razilator\Desktop\Courses\nth-coding\main.py", line 25, in <module>
    print(p.age, p.__dict__)
  File "C:\Users\Razilator\Desktop\Courses\nth-coding\main.py", line 11, in age
    return self.__age
AttributeError: 'Person' object has no attribute '_Person__age'. Did you mean: '_Person__name'?

Process finished with exit code 1

Но если мы просто покажем __dict__, то выведется следующее, уже без age

C:\Users\Razilator\Desktop\Courses\nth-coding\venv\Scripts\python.exe C:/Users/Razilator/Desktop/Courses/nth-coding/main.py
{'_Person__name': 'Владислав'}

Process finished with exit code 0

А чтоб задать обратно, после удаления, то можно прописать наш setter:

p = Person('Владислав', 23)
del p.age
p.age = 25

print(p.__dict__)

Результат:

C:\Users\Razilator\Desktop\Courses\nth-coding\venv\Scripts\python.exe C:/Users/Razilator/Desktop/Courses/nth-coding/main.py
{'_Person__name': 'Владислав', '_Person__age': 25}

Process finished with exit code 0

Вот с такой легкостью можно работать с приватными закрытыми локальными свойствами через объект свойства Property.

Урок взят с канала selfedu

Комментарии к статье 0
Комментариев нет
Форма добавления комментария (необходима регистрация)