Можливо, навіть далеко не всі чули, що таке дескриптори, але точно всі використовували їх
Я кажу це так впевнено, оскільки @property — є дескриптором 😮

Вступ

Оригінально, цей клас не задумувався як декоратор, а лише як явний транслятор між атрибутом та набором методів — геттер, сеттер та делеттер
Виглядати це має ось так:

# https://docs.python.org/uk/3/library/functions.html#property
class C:
    def __init__(self):
        self._x = None

    def getx(self):
        return self._x

    def setx(self, value):
        self._x = value

    def delx(self):
        del self._x

    x = property(getx, setx, delx, "I'm the 'x' property.")

І “під капотом” у @property відбувається вся магія
Як зробити власний аналог — описано тут. Я ж хочу спробувати пояснити дескриптори простішим чином 😉

class CountDescriptor:
    def __init__(self, base_count=0):
        self.count = base_count

    def __get__(self, instance, owner):
        if instance is None:  # зчитуємо атрибут класу
            return self.count
        return self.count + instance.count


class Container:
    total = CountDescriptor(10)

    def __init__(self, count=15):
        self.count = count

print(Container.total)
print(Container().total)
print(Container(50).total)

Виглядає складно? 😨

Нічьо, зараз розберемось 😎

Клас CountDescriptor має метод __get__, отже є дескриптором
У цього класу також є атрибут count, що задається у конструкторі

Якщо атрибут (у нас — total) є дескриптором, то при спробі зчитати атрибут, Пайтон виконає у нього метод __get__, передавши першим аргументом об’єкт, а другим — клас цього об’єкту
Якщо ж зчитується атрибут класу, як перший атрибут буде передано None

У самому методі ми перевіримо це, і змінимо логіку:

  1. якщо зчитується атрибут класу, то результатом у методі буде власний атрибут count

  2. якщо зчитується атрибут об’єкту, то результатом буде власний атрибут count і доданий до нього атрибут count переданого об’єкту

Тепер перейдемо до класу Container
Цей клас має звичайний атрибут count, зі значенням за замовчуванням 10, у конструкторі
І головне, що має цей клас — атрибут-дескриптор: total

Отже:

  • для атрибуту total класу Container виконається умова 1,
    відповідно значення буде 10

  • для атрибуту total об’єкту Container() виконається умова 2,
    відповідно значення буде 25 (10 + 15)

  • для атрибуту total об’єкту Container(50) виконається умова 2,
    відповідно значення буде 60 (10 + 50)

Якщо все ж складно, можете погратись з цим кодом у моєму JupyterLite, або продебагати код і побачити як усі дії відбуваються наяву 🤔

Продебагати онлайн можна у Python Tutor

Усе те саме працює і для зміни значення атрибуту (__set__) та видалення атрибуту (__delete__). Якщо хоча б один з цих методів є у класі, його можна використовувати як дескриптор 🤓

Для чого ж можна використовувати дескриптори у реальному світі?)

Для всього 👀
Тобто, це всього лиш інструмент 😅
Він допомагає приховати складну реалізацію, при цьому залишивши дуже зручний інструмент у вигляді атрибуту

З поширених прикладів, це поля БД у ORM (зміна атрибута у об’єкті потім повпливає на зміни у БД), вищезгадані @property, а також його друзі @classmethod та @staticmethod, і навіть самі методи як такі 🤯
Це все прямим текстом пише в документації

За допомогою дескрипторів можна просто реалізувати кешування атрибутів, які можуть рідко використовуватись

А ще, якби це дивно не виглядало, методи дескриптора можуть бути асинхронними, і це відкриває ще більше можливостей, звісно зі своєю ложкою дьогтю у вигляді заплутаного використання 🥲

Післямови не буде, бо я такого не вмію 😢

Якщо вам подобається такий контент, підписуйтесь на мій телеграм-канал:
Python просто | з Коропом

Поділись своїми ідеями в новій публікації.
Ми чекаємо саме на твій довгочит!
Вітя
Вітя@kor0p

Python SDET @ ajax.systems

816Прочитань
10Автори
17Читачі
Підтримати
На Друкарні з 14 квітня

Більше від автора

Вам також сподобається

  • Які книги з JavaScript слід читати у 2024 році?

    Чому варто вивчати JavaScript у 2024 році? Які книги обрати для вивчення цієї мови програмування? У цій статті ми розглядаємо ключові аргументи на користь вивчення JavaScript у 2024 році та поділимося переліком ресурсів, які допоможуть вам у цьому.

    Теми цього довгочиту:

    Javascript
  • Партиціювання у Kafka

    Пост про партиції в Kafka. Офсети. Визначення партиції. Динамічне розширення. Порядок і усунення дублікатів. Скільки треба вибирати партциій для топіка? Стратегії партиціювання.

    Теми цього довгочиту:

    Kafka
  • λanguage: Неформальний опис мови

    Автор пояснює, як написати парсер, інтерпретатор, компілятор, та інші складові власної мови програмування. Описується синтаксис мови, особливості реалізації функцій, умовних конструкцій та інших елементів мови.

    Теми цього довгочиту:

    Js

Коментарі (0)

Підтримайте автора першим.
Напишіть коментар!

Вам також сподобається

  • Які книги з JavaScript слід читати у 2024 році?

    Чому варто вивчати JavaScript у 2024 році? Які книги обрати для вивчення цієї мови програмування? У цій статті ми розглядаємо ключові аргументи на користь вивчення JavaScript у 2024 році та поділимося переліком ресурсів, які допоможуть вам у цьому.

    Теми цього довгочиту:

    Javascript
  • Партиціювання у Kafka

    Пост про партиції в Kafka. Офсети. Визначення партиції. Динамічне розширення. Порядок і усунення дублікатів. Скільки треба вибирати партциій для топіка? Стратегії партиціювання.

    Теми цього довгочиту:

    Kafka
  • λanguage: Неформальний опис мови

    Автор пояснює, як написати парсер, інтерпретатор, компілятор, та інші складові власної мови програмування. Описується синтаксис мови, особливості реалізації функцій, умовних конструкцій та інших елементів мови.

    Теми цього довгочиту:

    Js