Класс-декоратор Python: ограничение изменения результата между вызовами

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

Другие упражнения по этой теме: Классы-декораторы Python: задачи на call, методы и состояние.

Сглаживающий декоратор телеметрии

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

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

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

Реализуйте класс-декоратор, который хранит последнее подтверждённое показание, сглаживает скачки по описанному правилу и предоставляет метод сброса опорной точки.

Что уже дано

В редакторе объявлен класс StepLimiter с заготовками методов __init__, reset и __call__. Вспомогательные функции для тестирования датчиков доступны во время запуска, реализовывать их заново не требуется.

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

Реализуйте класс StepLimiter(func, threshold) со следующим поведением:

  • Конструктор принимает вызываемый объект func (обычную функцию модуля, возвращающую целые числа в диапазоне от -1 000 000 до 1 000 000) и неотрицательный целый порог threshold (от 0 до 1 000 000). При создании экземпляр не имеет сохранённой базы отсчёта.
  • Экземпляр вызывается как функция через __call__(*args, **kwargs) и передаёт аргументы в func без изменений. Исходная функция вызывается ровно один раз за обращение.
  • Первый сырой результат после инициализации или сброса возвращается без изменений и сохраняется как текущая база отсчёта.
  • При последующих вызовах, если модуль разности между новым сырым значением и текущей базой не превышает threshold, возвращается сырое значение, и оно становится новой базой.
  • Если разность строго больше threshold, возвращается значение прежней базы, сдвинутое ровно на threshold в сторону сырого значения (увеличенное или уменьшенное). Именно это возвращённое скорректированное значение сохраняется как новая база отсчёта; отклонённый сырой замер сохранять нельзя.
  • Метод reset() удаляет сохранённую базу и переводит декоратор в исходное неинициализированное состояние. Возвращаемое значение для reset() не регламентируется.
  • Декоратор рассчитан на работу с обычными функциями уровня модуля (от 0 до 1000 вызовов); поддержка рекурсии, методов классов и протокола дескрипторов не требуется.

Ввод и вывод

Потоки stdin и stdout не используются: считывать ввод и вызывать print() не нужно. Проверяющая система выполняет ваш скрипт, получает из глобальной области видимости класс верхнего уровня StepLimiter, создаёт декорированные экземпляры и проверяет их вызовы и метод сброса.

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

probe = make_call_probe([["return", 0], ["return", 10], ["return", -5], ["return", 20]])
read = StepLimiter(probe.compute, 3)
print(read())
print(read())
print(read())
read.reset()
print(read())

Вывод:

0
3
0
20
РешениеPython

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

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

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