functools: lru_cache и cached_property
Кэшируйте ресурсоёмкие вычисления с помощью lru_cache и cached_property.
«functools: lru_cache и cached_property» — бесплатный урок Python Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Python Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Python Academy содержит 4 уроков всего.
Что такое мемоизация?
Мемоизация кэширует результат вызова функции, используя её аргументы как ключ. Повторные вызовы с теми же аргументами сразу возвращают кэшированный результат.
def slow_fib(n):
if n < 2: return n
return slow_fib(n-1) + slow_fib(n-2)
# slow_fib(35) makes ~29 million calls
# With caching it makes only 35@lru_cache
@functools.lru_cache(maxsize=128) кэширует до maxsize последних результатов. Установите maxsize=None для кэша без ограничения размера.
import functools
@functools.lru_cache(maxsize=None)
def fib(n):
if n < 2: return n
return fib(n-1) + fib(n-2)
print(fib(50)) # instant@cache — начиная с Python 3.9
functools.cache — это сокращённая запись для lru_cache(maxsize=None): кэш без ограничения размера с более понятным именем.
import functools
@functools.cache
def factorial(n):
return n * factorial(n-1) if n else 1
print(factorial(10)) # 3628800Информация о кэше и его очистка
Кэшированные функции предоставляют .cache_info() (попадания, промахи и размер) и .cache_clear().
import functools
@functools.lru_cache(maxsize=100)
def square(n):
return n * n
for i in range(5): square(i % 3)
print(square.cache_info())
# CacheInfo(hits=2, misses=3, maxsize=100, currsize=3)
square.cache_clear()Политика вытеснения LRU
LRU (наименее недавно использованный) при заполнении кэша удаляет элемент, к которому обращались давнее всего.
import functools
@functools.lru_cache(maxsize=3)
def compute(n):
print(f"computing {n}")
return n**2
for x in [1,2,3,4,1]: # 4 evicts 1 (LRU), then 1 re-computes
compute(x)Только хешируемые аргументы
lru_cache требует, чтобы все аргументы были хешируемыми. Списки и словари нельзя хешировать; вместо них используйте кортежи.
import functools
@functools.lru_cache(maxsize=None)
def sum_tuple(t): # tuple is hashable
return sum(t)
print(sum_tuple((1,2,3))) # 6
# sum_tuple([1,2,3]) # TypeError@cached_property
functools.cached_property вычисляет свойство один раз и кэширует результат в экземпляре, заменяя дескриптор значением.
import functools
class Circle:
def __init__(self, r):
self.r = r
@functools.cached_property
def area(self):
import math
print("computing...")
return math.pi * self.r ** 2
c = Circle(5)
print(c.area) # computing... 78.53...
print(c.area) # 78.53... (cached, no print)cached_property и property
@property выполняет вычисление при каждом обращении. @cached_property вычисляет значение один раз и сохраняет результат в instance.__dict__.
import functools
class Expensive:
@property
def always(self): # runs every access
return sum(range(1_000_000))
@functools.cached_property
def once(self): # runs only first access
return sum(range(1_000_000))Потокобезопасность cached_property
cached_property не является потокобезопасным. Если несколько потоков обращаются к нему одновременно, вычисление может выполниться более одного раза. При необходимости используйте блокировку.
import functools, threading
class SafeCache:
_lock = threading.Lock()
@functools.cached_property
def data(self):
with self._lock:
return expensive_computation()Инвалидация cached_property
Удалите атрибут экземпляра, чтобы сделать кэш недействительным и принудительно выполнить вычисление при следующем обращении.
import functools
class Report:
@functools.cached_property
def summary(self):
return compute_summary()
r = Report()
_ = r.summary # computed
del r.summary # invalidate
_ = r.summary # recomputedИспользование lru_cache как кэша API
Кэшируйте ответы API в течение сеанса, чтобы избежать повторных сетевых запросов. Очищайте кэш, когда требуются свежие данные.
import functools, urllib.request, json
@functools.lru_cache(maxsize=32)
def get_user(user_id):
url = f"https://api.example.com/users/{user_id}"
with urllib.request.urlopen(url) as r:
return json.loads(r.read())
user = get_user(42) # network call
user = get_user(42) # cachedБыстрая проверка
Какой метод очищает все кэшированные результаты функции, оформленной декоратором @lru_cache?
Итоги
@lru_cache кэширует результаты функций, используя аргументы как ключи (аргументы должны быть хешируемыми). @cache — это псевдоним для кэша без ограничения размера. @cached_property кэширует вычисление свойства для каждого экземпляра. Просматривайте кэш с помощью cache_info() и сбрасывайте его с помощью cache_clear().
Часто задаваемые вопросы
Урок «functools: lru_cache и cached_property» бесплатный?
Да — полный текст урока «functools: lru_cache и cached_property» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Python Academy, подпишись на CoddyKit PRO. Курс Python Academy содержит 4 уроков всего.
Чему я научусь в уроке «functools: lru_cache и cached_property»?
Кэшируйте ресурсоёмкие вычисления с помощью lru_cache и cached_property. Ты практикуешь Python Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Python Academy?
Предыдущий опыт не требуется. Python Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «functools: lru_cache и cached_property»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Python Academy?
Да. Каждый урок Python Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- itertools: бесконечные и конечные итераторы
- itertools: комбинаторика
- functools: partial и reduce
- functools: lru_cache и cached_property