Моя проблема и почему
Я пытаюсь написать декоратор для метода класса @cachedproperty
. Я хочу, чтобы он вел себя так, что, когда метод сначала вызывается, метод заменяется его возвращаемым значением. Я также хочу, чтобы он вел себя как @property
, так что он не должен быть явно вызван. В принципе, он должен быть неотличим от @property
, за исключением того, что он быстрее, потому что он только вычисляет значение один раз, а затем сохраняет его. Моя идея заключается в том, что это не замедлит создание экземпляра, как определение его в __init__
.. Поэтому я хочу это сделать.
Что я пробовал
Сначала я попытался переопределить метод fget
property
, но он доступен только для чтения.
Затем я решил, что попытаюсь реализовать декоратор, который нужно вызвать в первый раз, но затем кэширует значения. Это не моя конечная цель декоратора типа собственности, который никогда не нужно называть, но я думал, что это будет более простая проблема для решения в первую очередь. Другими словами, это нерабочее решение для немного более простой проблемы.
Я пробовал:
def cachedproperty(func):
""" Used on methods to convert them to methods that replace themselves
with their return value once they are called. """
def cache(*args):
self = args[0] # Reference to the class who owns the method
funcname = inspect.stack()[0][3] # Name of the function, so that it can be overridden.
setattr(self, funcname, func()) # Replace the function with its value
return func() # Return the result of the function
return cache
Однако это не похоже на работу. Я тестировал это с помощью:
>>> class Test:
... @cachedproperty
... def test(self):
... print "Execute"
... return "Return"
...
>>> Test.test
<unbound method Test.cache>
>>> Test.test()
но я получаю сообщение о том, как класс не передал себя методу:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method cache() must be called with Test instance as first argument (got nothing instead)
В этот момент я и мои ограниченные знания о глубоких методах Python очень смущены, и я понятия не имею, где мой код поступил неправильно или как его исправить. (Я никогда не пытался писать декоратор раньше)
Вопрос
Как я могу написать декоратор, который будет возвращать результат вызова метода класса при первом обращении (например, @property
), и заменить его на кешированное значение для всех последующих запросов?
Надеюсь, этот вопрос не слишком запутан, я пытался объяснить это так, как мог.