Кэширование 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
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- Functools.wraps в Python: имя функции и атрибут wrapped
- Декоратор Circuit Breaker на Python: остановка вызовов после сбоев
- Декораторы Python: проверка цепочки wrapped и метаданных функции
- Декоратор Python: логирование только медленных вызовов
- Rate limiter на Python: декоратор со скользящим окном запросов
- Retry и fallback на Python: декоратор повторов с резервным вызовом
