Как получить имя атрибута дескриптора из __get__?

При реализации дескриптора можно использовать __set_name__ зарегистрировать, под каким именем атрибута был задан дескриптор.

Хотя предположим, что мы должны установить более одного атрибута для одного и того же дескриптора, тогда, похоже, нет никакого способа узнать, через какое имя был получен доступ к дескриптору в __get__ а также __set__ метод.

Код

class Prop:
    def  __init__(self):
        self._names = {}

    def __set_name__(self, owner, name):
        print(f'Attribute \'{name}\' was set to a Prop')

        if owner in self._names:
            self._names[owner].append(name)
        else:
            self._names[owner] = [name]

    def __get__(self, instance, owner):
        print(f'Prop was accessed through one of those: {self._names[owner]}')

prop = Prop()

class Foo:
    bar = prop
    baz = prop

foo = Foo()
foo.baz

Выход

Attribute 'bar' was set to a Prop
Attribute 'baz' was set to a Prop
Prop was accessed through one of those: ['bar', 'baz']

Есть ли чистый и общий способ узнать, по какому атрибуту был получен доступ к дескриптору?

1 ответ

Решение

Есть ли чистый и общий способ узнать, по какому атрибуту был получен доступ к дескриптору?

Нет, нет чистого и общего способа.

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

class Descriptor:
    def __get__(self, instance, owner, name=None):
        print(f"Property was accessed through {name}")
        return 'foo'

p = Descriptor()

class Test:
    a = p
    b = p

    def __getattribute__(self, name):
        for klass in type(self).__mro__:
            if name in klass.__dict__ and isinstance(klass.__dict__[name], Descriptor):
                return klass.__dict__[name].__get__(self, klass, name)
        else:
            return object.__getattribute__(self, name)
Другие вопросы по тегам