2 типа дескрипторов в Python

В этом руководстве вы узнаете о различиях между дескрипторами данных и дескрипторами, не относящимися к данным.

Дескрипторы в Python бывают двух типов:

  • Дескрипторы данных — это объекты класса, реализующего метод __set__(и/или метод __delete__).
  • Дескрипторы, не являющиеся данными, — это объекты класса, имеющие только метод __get__.

Оба типа дескрипторов могут опционально реализовывать метод __set_name__. Метод __set_name__ не влияет на классификацию дескрипторов.

Типы дескрипторов определяют, как Python разрешает поиск атрибутов объекта.

Дескриптор без данных

Если класс использует дескриптор, не являющийся данными, Python сначала будет искать атрибут в атрибутах экземпляра (instance.__dict__). Если Python не находит атрибут в атрибутах экземпляра, он будет использовать дескриптор данных.

Давайте посмотрим на следующий пример.

  • Сначала определите класс FileCount, не являющийся дескриптором данных, который имеет метод __get__, который возвращает количество файлов в папке:
class FileCount:
    def __get__(self, instance, owner):
        print('The __get__ was called')
        return len(os.listdir(instance.path))
  • Во-вторых, определите класс Folder, который использует дескриптор FileCount:
class Folder:
    count = FileCount()

    def __init__(self, path):
        self.path = path
  • В-третьих, создайте экземпляр класса Folder и получите доступ к атрибуту count:
folder = Folder('/')
print('file count: ', folder.count)

Python вызвал дескриптор __get__:

The __get__ was called
file count:  32
  • После этого установите атрибут count экземпляра папки на 100 и получите доступ к атрибуту count:
folder.__dict__['count'] = 100
print('file count: ', folder.count)

Выход:

file count:  100

В этом примере Python может найти атрибут count в словаре экземпляра __dict__. Поэтому он не использует дескрипторы данных.

Дескриптор данных

Если у класса есть дескриптор данных, Python сначала будет искать атрибут экземпляра в дескрипторе данных. Если Python не находит атрибут, он будет искать его в словаре экземпляра(__dict__).

Пример:

  • Сначала определите класс дескриптора координат:
class Coordinate:
    def __get__(self, instance, owner):
        print('The __get__ was called')

    def __set__(self, instance, value):
        print('The __set__ was called')
  • Во-вторых, определите класс Point, который использует дескриптор координат:
class Point:
    x = Coordinate()
    y = Coordinate()
  • В-третьих, создайте новый экземпляр класса Point и присвойте значение атрибуту x экземпляра p:
p = Point()
p.x = 10

Выход:

The __set__ was called

Python вызвал метод __set__ дескриптора x.

  • Наконец, получите доступ к атрибуту x экземпляра p:
p.x

Выход:

The __get__ was called

Python вызвал метод __get__ дескриптора x.

Похожие посты
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *