Понять поведение __delete__ в дескрипторе с множественным назначением в одной строке - PullRequest
1 голос
/ 21 апреля 2020

Это дескриптор, созданный для (частично) эмуляции класса свойств в python, но ленивым образом.

# non useful methods and implementations get abstracted away
class LazyProperty(object):
    def __init__(self, fget=None):
        self.fget = fget

    def __get__(self, obj, objtype=None):
        result = obj.__dict__[self.fget.__name__] = self.fget(obj)
        return result

    def __delete__(self, obj):
        pass

Создание другого класса и декорирование метода в этом вновь определенном классе с помощью LazyProperty как следует

class MyClass:
    @LazyProperty
    def x(self):
        print("called once")
        return 5


my_class = MyClass()
my_class.x
my_class.x

Запустите этот код, я ожидал, что function x в MyClass будет вызываться только один раз , но на самом деле он вызывается дважды . Если закомментировать метод __delete__ из LazyProperty и запустить его снова, то все вернулось назад, чтобы соответствовать ожиданиям - function x вызывается только один раз. Точно такое же поведение было обнаружено при замене __delete__ на __set__. Я чувствую, что какой-то механизм работает под капотом, который вызывает эту проблему, возможно, из-за того, как я назначаю переменные, у кого-нибудь есть идеи?

1 Ответ

3 голосов
/ 21 апреля 2020

Наличие метода __set__ или __delete__ делает дескриптор дескриптором данных . Дескрипторы данных имеют приоритет над записями __dict__ экземпляра, поэтому __get__ вашего дескриптора вызывается, даже если предыдущий вызов уже кэшировал значение в экземпляре dict.

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

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