Кэширование Python: постройте ключ из выбранных аргументов функции

Напишите решение на Python и проверьте его на странице.

Другие упражнения по этой теме: Декораторы Python: задачи на retry, rate limiter, кэш и Circuit Breaker.

Кэширование по проекции аргументов

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

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

Реализуйте параметризованный декоратор с селектором проекции ключей и определите, сколько фактических обращений к вычислительному ядру произойдёт при обработке чередующейся серии запросов.

Что уже дано

В заготовке объявлена фабрика декоратора projected_cache(selector), которую вам предстоит реализовать.

Что нужно сделать

Реализуйте функцию-фабрику projected_cache(selector).

Она принимает вызываемый объект selector и возвращает декоратор. Этот декоратор принимает целевую функцию func и возвращает функцию-обёртку, сохраняющую сигнатуру *args, **kwargs исходной функции.

Правила работы обёртки:

  • При каждом вызове обёртка передаёт полученные аргументы *args и **kwargs в selector без изменений. Селектор возвращает хэшируемый ключ проекции.
  • Если для полученного ключа результат ещё не вычислялся, обёртка вызывает целевую функцию func(*args, **kwargs), сохраняет возвращённый результат в кэше и возвращает его.
  • Если для такого ключа результат уже сохранён, функция func повторно не вызывается — обёртка сразу возвращает кэшированное значение (включая None, False, 0 и пустые строки).
  • Второстепенные параметры, проигнорированные селектором (например, словари или списки со служебными полями), не должны влиять на эквивалентность запросов.
  • Кэш должен быть изолированным для каждой декорированной функции, даже если один и тот же декоратор применяется к нескольким функциям повторно.
  • Различные ключи проекции должны кэшироваться раздельно, даже при совпадении их хэш-значений.
  • Никаких ограничений по размеру, времени жизни (TTL), механизмов сброса или вытеснения реализовывать не требуется.

После выполнения вашего скрипта проверяющая система импортирует объект верхнего уровня projected_cache и тестирует его на предоставленных селекторах и вычислениях.

Ввод и вывод

Стандартный ввод stdin не используется. Печатать через print в stdout ничего не нужно: проверяющая система напрямую вызывает созданные функции и проверяет их возвращаемые значения.

Пример использования

probe = make_report_probe(['region', 'period'], [(("north", 1), 17)])
report = projected_cache(probe.select)(probe.compute)
print(report({'region': 'north', 'period': 1, 'trace': 'a'}))
print(report({'region': 'north', 'period': 1, 'trace': 'b'}))
print(observe_report_probe(probe)['call_count'])

Вывод:

17
17
1
РешениеPython

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Связанные задачи