functools.lru_cache()

@functools.lru_cache(user_function)

@functools.lru_cache(maxsize=128, typed=False)

Декоратор для обертывания функции мемоизирующим вызываемым объектом, который сохраняет до максимального размера maxsize самые последние вызовы. Это может сэкономить время, когда дорогостоящая функция или функция, связанная с вводом-выводом, периодически вызывается с одними и теми же аргументами.

Поскольку для кэширования результатов используется словарь, позиционные и ключевые аргументы функции должны быть хешируемыми.

Различные шаблоны аргументов можно рассматривать как отдельные вызовы с отдельными записями в кэше. Например, f (a = 1, b = 2) и f (b = 2, a = 1) различаются порядком их аргументов ключевого слова и могут иметь две отдельные записи кэша.

Если указана функция user_function, она должна быть вызываемой. Это позволяет применять декоратор lru_cache непосредственно к пользовательской функции, оставляя для параметра maxsize значение по умолчанию 128:

@lru_cache
def count_vowels(sentence):
    sentence = sentence.casefold()
    return sum(sentence.count(vowel) for vowel in 'aeiou')

Если для maxsize задано значение None, функция LRU отключена, и кэш может неограниченно увеличиваться.

Если для параметра typed установлено значение true, аргументы функций разных типов будут кэшироваться отдельно. Например, f (3) и f (3.0) будут обрабатываться как отдельные вызовы с разными результатами.

Обернутая функция оснащена функцией cache_parameters (), которая возвращает новый dict, показывающий значения maxsize и typed. Это только для информационных целей. Изменение значений не имеет никакого эффекта.

Чтобы помочь измерить эффективность кеша и настроить параметр maxsize, обернутая функция оснащена функцией cache_info (), которая возвращает именованный кортеж, показывающий hits, misses, maxsize и currsize. В многопоточной среде hits и misses являются приблизительными.

Декоратор также предоставляет функцию cache_clear () для очистки или аннулирования кеша.

Исходная базовая функция доступна через атрибут __wrapped__. Это полезно для самоанализа, для обхода кеша или для перенастройки функции другим кешем.

Кэш LRU (наименее недавно использованный) работает лучше всего, когда самые последние вызовы являются лучшими предикторами предстоящих вызовов (например, самые популярные статьи на сервере новостей, как правило, меняются каждый день). Ограничение размера кеша гарантирует, что кеш не будет расти без ограничений для длительных процессов, таких как веб-серверы.

В общем, кэш LRU следует использовать только тогда, когда вы хотите повторно использовать ранее вычисленные значения. Соответственно, нет смысла кэшировать функции с побочными эффектами, функции, которые должны создавать отдельные изменяемые объекты при каждом вызове, или нечистые функции, такие как time () или random ().

Пример кеша LRU для статического веб-контента:

@lru_cache(maxsize=32)
def get_pep(num):
    'Получить текст предложения по усовершенствованию Python'
    resource = 'http://www.python.org/dev/peps/pep-%04d/' % num
    try:
        with urllib.request.urlopen(resource) as s:
            return s.read()
    except urllib.error.HTTPError:
        return 'Not Found'

>>> for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991:
...     pep = get_pep(n)
...     print(n, len(pep))

>>> get_pep.cache_info()
CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)

Пример эффективного вычисления чисел Фибоначчи с использованием кеша для реализации метода динамического программирования:

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

>>> [fib(n) for n in range(16)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]

>>> fib.cache_info()
CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)

Новое в версии 3.2.

Изменено в версии 3.3: Добавлена опция typed.

Изменено в версии 3.8: Добавлена опция user_function.

Новое в версии 3.9: Добавлена функция cache_parameters ()

Last updated