Почему Python Descriptor работает для атрибута уровня класса, а не для атрибута уровня экземпляра - PullRequest
0 голосов
/ 28 мая 2018

Почему дескриптор Python работает для атрибута уровня класса, а не для атрибута уровня экземпляра.

class PropDescriptor:

    def __init__(self,*args):
        print("Init {} {}".format(type(self),args))
        self.value = 0

    def __get__ (self,instance,owner):
        print("get using descriptor")
        return instance.instance_att

    def __set__(self, instance, value):
        print("set using descriptor")
        instance.instance_att = value


class TestClass:
    class_att = PropDescriptor()

    def __init__(self):
        self.instance_att = PropDescriptor()



t = TestClass()
print("set instance level...")
t.instance_att = 3

print("\nget instance level...")
print(t.instance_att)

print("\nset class level...")
t.class_att = 4

print("\nget class level...")
print(t.class_att)

Вывод:

Init <class '__main__.PropDescriptor'> ()
Init <class '__main__.PropDescriptor'> ()
set instance level...

get instance level...
3

set class level...
set using descriptor

get class level...
get using descriptor
4

похоже, что дескриптор не используется для instance_att.

Я нашел этот идентичный вопрос, но он на самом деле не отвечает на вопрос. Все ответы относятся ко второму вопросу в посте.

Документация Python указывает:

Привязка экземпляра

При привязке к экземпляру объекта ax преобразуется

в вызов: type(a).__dict__['x'].__get__(a, type(a)).

Но: первая часть (мой эквивалент кода) type(t).__dict__["instance_att"], вызывает KeyError какtype(t).__dict__ не имеет такого атрибута.Это уровень экземпляра att.Не так ли?

Чего мне не хватает?

1 Ответ

0 голосов
/ 28 мая 2018

Быстрый ответ: t.instance_att обрабатывается object.__getattribute__, и его определение просто игнорирует методы __get__ и __set__ значения, если оно найдено в словаре экземпляров t.

* 1007.* Более длинный ответ начинается с объяснения того, как обрабатывается поиск атрибутов.Они не встроены в язык, а обрабатываются методом __getattribute__ некоторого класса.Будучи редко переопределенным, это почти всегда означает object.__getattribute__, который реализован в C как _PyObject_GenericGetAttrWithDict.

Вместо того, чтобы подробно объяснять этот алгоритм здесь, я отсылаю вас к https://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/,, в котором есть фантастические диаграммы, объясняющие как поиск атрибутов объектов, так и поиск атрибутов классов.


Здесь, по крайней мере, один ответ здесь, в переполнении стека, включает диаграмму, но я не могу найти ее вмомент, поэтому я прошу прощения за сторонние ссылки.Я включу ссылку (или, возможно, закрою ее как дубликат), если смогу ее найти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...