Вы должны хотя бы вызвать lru_cache без аргументов:
@lru_cache()
def f():
#content of the function
Таким образом, lru_cache инициализируется с параметрами по умолчанию.
Это связано с тем, что декораторы в Python (с нотацией @
) — это специальные функции, которые оцениваются и вызываются, когда интерпретатор импортирует модуль.
Когда вы пишете @decorator_name
, вы сообщаете python, что decorator_name
— это функция, которая будет вызываться с функцией (или классом), определенной после нее. Пример:
@my_decorator
def function():
pass
эквивалентно:
def function():
pass
decorated_function = my_decorator(function)
Декоратор lru_cache
немного сложнее, потому что перед оберткой функции он должен создать кеш (связанный с функцией), а затем обернуть функцию другой функцией, которая будет выполнять управление кешем. Вот (сокращенный) код реализации CPython. :
def lru_cache(maxsize=128, typed=False):
# first, there is a test about the type of the parameters
if maxsize is not None and not isinstance(maxsize, int):
raise TypeError('Expected maxsize to be an integer or None')
# then, the decorating function is created, this function will be called each time you'll call the 'cached' function
def decorating_function(user_function):
wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo) # in _lru_wrapper is all the magic about the cache management, it is a 2nd layer of decorator
return update_wrapper(wrapper, user_function)
return decorating_function
Итак, когда вы написали только
@lru_cache
def f():
python под названием lru_cache(f)
, и определенно он не был создан для таких вещей.
Чтобы сделать его совместимым с этой записью, мы должны добавить тест, чтобы проверить, является ли первый параметр (maxsize) вызываемой функцией:
def lru_cache(maxsize=128, typed=False):
# first, there is a test about the type of the parameters
if callable(maxsize):
def decorating_function(user_function):
wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo)
return update_wrapper(wrapper, user_function)
return decorating_function(maxsize) # yes, maxsizeis the function in this case O:)
if maxsize is not None and not isinstance(maxsize, int):
raise TypeError('Expected maxsize to be an integer or None')
# then, the decorating function is created, this function will be called each time you'll call the 'cached' function
def decorating_function(user_function):
wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo) # in _lru_wrapper is all the magic about the cache management, it is a 2nd layer of decorator
return update_wrapper(wrapper, user_function)
return decorating_function
person
Cédric Julien
schedule
10.11.2017
@lru_cache
без круглых скобок работает, начиная с Python 3.8. - person Boris   schedule 06.12.2019