CachedProperty
, как описано в его названии, предназначено для использования в качестве декоратора для методов в теле класса (не в автономных функциях), которые затем будут вести себя как обычные "свойства" Python, но которые будут "кэшироваться",: -)
В вашем примере кода вы пытаетесь применить его к функции уровня модуля, и это не сработает - потому что этот декоратор преобразует функцию в объект, который зависит от механизмов доступа к атрибутамэто работает только для членов класса (то есть: «протокол дескриптора», который работает для объектов, которые реализуют один из методов __get__
, __set__
или __del__
).
Идея декоратора вНа самом деле Python довольно прост - у него нет особых случаев.Очевидный «особый случай» в вашем коде обусловлен природой возвращаемого объекта.
Итак, , кратко - декоратор - это просто вызываемый объект, который принимает один единственный параметр, который является еще одним вызываемым - обычно это функция или класс, и возвращает другой объект (не обязательно вызываемый), который заменит первый.
Итак, для простого декораторанапример:
def logcalls(func):
def wrapper(*args, **kw):
print(f"{func} called with {args} and {kw}")
return func(*args, **kw)
return wrapper
его можно использовать как:
@logcalls
def add(a, b):
return a + b
и эквивалентно:
def add(a, b):
return a + b
add = logcalls(a + b)
Это просто!
Сложность может возникнуть, когда вы хотите передать дополнительные параметры для декоратора, тогда вам нужно иметь «этап», который будет принимать эти параметры настройки и возвращать вызываемый объект, который будет принимать оформленный объект в качестве единственного параметра.В некоторых основах кода это приводит к тому, что декоратор состоит из 3-х уровней вложенных функций, которые могут быть полезны.
Если CachedProperty
выше будет реализовывать метод __call__
, то, кроме __get__
, он будет работать и для классов модулей (при условии, что у него есть подходящее место для записи значений классов - дескрипторы получают экземплярони прикреплены бесплатно).Также стоит отметить, что для кеширования вызовов обычных функций стандартная библиотека Python имеет декоратор в модуле functools - functools.lru_cache()