Пропустить до содержимого

Как использовать кэш в Python?

[

Кеширование в Python с использованием стратегии LRU Cache

В Python существует множество способов достижения быстродействия и отзывчивости приложений. Одним из подходов является кеширование, которое, если использовать его правильно, делает приложение гораздо быстрее и снижает нагрузку на вычислительные ресурсы. Модуль functools в Python поставляется с декоратором @lru_cache, который позволяет вам кэшировать результаты ваших функций, используя стратегию Least Recently Used (LRU). Это простая, но мощная техника, которую вы можете использовать для оптимизации вашего кода с помощью кеширования.

Оглавление

  • Кэширование и его применение
    • Реализация кеша с использованием словаря Python
    • Cтратегии кэширования
    • Погружение в стратегию кэширования LRU
    • Вглядывание внутрь кэша LRU
  • Использование @lru_cache для реализации кэша LRU в Python
    • Игра с лестницей
    • Измерение времени работы кода
    • Использование мемоизации для улучшения решения
    • Распаковка функциональности @lru_cache
  • Добавление истечения срока кэша
    • Исключение записей из кэша на основе времени и памяти
    • Кэширование статей с помощью нового декоратора
  • Заключение

В конце этого руководства у вас будет глубокое понимание того, как работает кэширование и как воспользоваться этим в Python.

Кэширование и его применение

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

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

Что произойдет, если пользователь решит многократно перемещаться туда и обратно между несколькими новостными статьями? Если данные не кешируются, ваше приложение должно будет загружать тот же контент каждый раз! Это сделает систему пользователя медленнее и создаст дополнительную нагрузку на сервер, на котором размещаются статьи.

Более лучшим подходом будет хранение контента локально после загрузки каждой статьи. Затем, когда пользователь решит открыть статью в следующий раз, ваше приложение может открывать содержимое из локальной копии вместо повторной загрузки с сервера. В компьютерной науке этот прием называется кешированием.

Реализация кеша с использованием словаря Python

В Python вы можете реализовать кэширование с использованием словаря. Возвращаясь к примеру с новостным приложением, вместо того, чтобы каждый раз обращаться к серверу для скачивания статьи, вы можете проверить, есть ли содержимое в вашем кэше, и обращаться к серверу только в случае его отсутствия. Вы можете использовать словарь, чтобы хранить загруженные статьи, используя URL в качестве ключа:

cache = {}
def download_article(url):
if url in cache:
return cache[url]
else:
article = fetch_article_from_server(url)
cache[url] = article
return article

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

В Python модуль functools предоставляет более удобное решение для кэширования - декоратор @lru_cache.

Использование @lru_cache для реализации кэша LRU в Python

Декоратор @lru_cache в Python позволяет вам автоматически кэшировать результаты функции и избегать повторных вычислений для вызовов с одинаковыми аргументами.

Для применения декоратора @lru_cache к функции достаточно просто его указать перед определением функции:

from functools import lru_cache
@lru_cache
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)

В этом примере функция fibonacci реализует рекурсивный алгоритм вычисления чисел Фибоначчи. Декоратор @lru_cache автоматически кэширует результаты вызовов функции fibonacci и избегает повторных вычислений для одинаковых аргументов. Это существенно повышает производительность функции.

Игра с лестницей

Давайте в качестве примера рассмотрим простую задачу - игру с лестницей. В этой игре у вас есть лестница с определенным количеством ступеней, и вы можете подняться на вершину лестницы, делая каждый раз шаг, увеличивая высоту шага на 1 или 2. Ваша задача - выяснить, сколько существует различных способов подняться на вершину лестницы. Например, для лестницы с 3 ступенями есть 3 различных способа подняться наверх: 1-1-1, 1-2 и 2-1.

Код для решения этой задачи может выглядеть так:

@lru_cache
def climb_stairs(n):
if n <= 2:
return n
return climb_stairs(n-1) + climb_stairs(n-2)

В этом примере функция climb_stairs решает задачу рекурсивно. Если количество ступеней меньше или равно 2, то ответом будет само количество ступеней. В противном случае результат вычисления равен сумме количеств способов подняться на n-1 ступень и n-2 ступень. Декоратор @lru_cache автоматически кэширует результаты вызовов функции climb_stairs и избегает повторных вычислений для одинаковых аргументов.

Добавление истечения срока кэша

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

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

import time
from functools import lru_cache
@lru_cache
def get_article_content(url):
article = fetch_article_from_server(url)
return article
@lru_cache(maxsize=128, typed=False, expire=3600)
def get_article_content_with_expiry(url):
article = fetch_article_from_server(url)
return article

В этом примере функция get_article_content_with_expiry добавляет параметр expire, который определяет, через сколько секунд должны истечь данные в кеше. По умолчанию этот параметр равен 3600 секундам (один час). Дополнительно вы также можете использовать параметры maxsize и typed для управления размером кеша и строгости типизации ключей.

Заключение

В этом руководстве вы узнали о кэшировании и его использовании в Python с помощью стратегии LRU Cache. Вы рассмотрели различные стратегии кэширования и научились реализовывать кэш с использованием декоратора @lru_cache. Также вы научились расширять функциональность этого декоратора для добавления истечения срока кэша.