Класс-декоратор Python: ограничение глубины рекурсии
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Классы-декораторы Python: задачи на call, методы и состояние.
Ограничитель глубины вызовов
Игровой бот исследует процедурный лабиринт с помощью рекурсивной функции, переходящей из комнаты в комнату. Чтобы алгоритм не уходил в бесконечные петли и не тратил ресурсы впустую, вызовы этой функции защищают специальным классом-декоратором с настраиваемым лимитом глубины.
Декоратор следит за количеством текущих вложенных шагов. Если уровень активной рекурсии уже достиг установленного предела, декоратор блокирует попытку пройти дальше и сразу возвращает None, вообще не вызывая целевую функцию. Когда же порог ещё не превышен и шаг действительно выполняется, счётчик активной глубины увеличивается на единицу, а при возврате значения или ошибке строго откатывается обратно. Исторический максимум глубины при этом обновляется только для тех вызовов, которые реально состоялись.
Реализуйте класс-декоратор, который отсекает вызовы на границе лимита, надёжно восстанавливает счётчик текущей глубины и сохраняет наибольшую глубину среди фактически запущенных шагов.
Что уже дано
В редакторе представлена заготовка класса DepthGuard с методами __init__ и __call__, которые вам предстоит реализовать. Дополнительная вспомогательная функция observe_depth_guard уже доступна в тестовом окружении для проверки сценариев выполнения; реализовывать её не требуется.
Что нужно сделать
Реализуйте класс DepthGuard со следующим поведением:
- Конструктор
DepthGuard(func, max_depth)принимает исходную синхронную функциюfuncи целое числоmax_depth(от0до20) — максимальное допустимое количество одновременно выполняющихся вызовов целевой функции для данного экземпляра декоратора. - При инициализации экземпляра атрибуты
active_depthиpeak_depthустанавливаются равными0. - Экземпляр вызывается через метод
__call__(*args, **kwargs)с произвольными позиционными и именованными аргументами, которые должны передаваться в целевую функцию без изменений. - Если в момент вызова значение
active_depthуже равноmax_depth, декоратор немедленно возвращаетNone. Исходная функцияfuncпри этом не вызывается, а значениеpeak_depthне изменяется. - Если лимит ещё не достигнут, перед вызовом целевой функции
active_depthувеличивается на1. Значениеpeak_depthобновляется наибольшим фактически достигнутым уровнем активной глубины. - При завершении фактически запущенного вызова — как при успешном возврате результата, так и при возникновении любого исключения (включая семейство
BaseException) — значениеactive_depthгарантированно возвращается к предыдущему уровню. Зафиксированный максимумpeak_depthсохраняется между последующими вызовами. - Если целевая функция вернула значение, декоратор возвращает его без изменений. Если целевая функция выбросила исключение, декоратор не подавляет и не подменяет его, а пробрасывает дальше.
- Каждый созданный экземпляр
DepthGuardхранит собственное независимое состояние счетчиков, даже если одна декорированная функция вызывает другую. - Реализовывать сохранение метаданных или связывание методов через дескрипторы в этой задаче не требуется.
Ввод и вывод
Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля класс верхнего уровня DepthGuard и вызывает его с проверочными аргументами.
Пример использования
def explore(steps):
if steps == 0:
return 'exit'
return guarded(steps - 1)
guarded = DepthGuard(explore, 2)
print(guarded(3))
print(guarded.active_depth, guarded.peak_depth)
print(guarded(1))
Вывод:
None 0 2 exit
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- Класс-декоратор Python: когда вызывается init
- Класс-декоратор метода Python: почему теряется self
- Класс-декоратор Python: ограничение изменения результата между вызовами
- Класс-декоратор Python: баланс доступных вызовов функции
- Класс-декоратор Python: изменение аргумента первых N вызовов
- Класс-декоратор Python: буфер событий и пакетная запись
