Класс-декоратор Python: проверка монотонности результатов
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Классы-декораторы Python: задачи на call, методы и состояние.
Монотонная контрольная сумма
Модуль валидации непрерывно принимает блоки данных через функцию расчёта контрольной суммы. Согласно регламенту, значения сумм должны строго монотонно возрастать от одного блока к другому. Чтобы контролировать поток, функцию оборачивают в специальный класс-декоратор: он запоминает последнее успешно подтверждённое значение и при каждом следующем вызове сверяет свежий результат с этим сохранённым эталоном.
Если функция выдаёт контрольную сумму, которая меньше сохранённого уровня или равна ему, декоратор возбуждает служебное исключение о нарушении монотонности. При этом испорченный результат отбрасывается, а прежний верный эталон остаётся без изменений, защищая последовательность от сбоя. Когда же поток данных переключается на новую серию блоков, инженер может вызвать метод reset_baseline(), чтобы принудительно сбросить прежнюю базу отсчёта. После такого сброса ближайший вызов принимается безоговорочно и становится новой точкой отсчёта.
Реализуйте класс-декоратор, который обеспечивает строгую монотонность возвращаемых значений, сохраняет последний валидный уровень при любых нарушениях и поддерживает ручной сброс контрольной базы.
Что уже дано
В среде выполнения уже доступен класс служебного исключения MonotonicityError (наследник ValueError). Также доступна вспомогательная утилита observe_monotonic_checksums, реализовывать которую не требуется.
В редакторе представлена заготовка класса MonotonicChecksum с методами __init__, __call__ и reset_baseline(), которые вам предстоит реализовать.
Что нужно сделать
Реализуйте класс-декоратор MonotonicChecksum(func) со следующими методами:
- Конструктор
__init__(self, func)принимает синхронный вызываемый объектfunc, возвращающий конечные числа из семейств целых чисел или чисел с плавающей точкой (включаяbool) в диапазоне от -1 000 000 до 1 000 000. Требования к хешируемости возвращаемых чисел отсутствуют. - Метод
__call__(self, *args, **kwargs)перехватывает вызов декорированной функции: - Аргументы
*argsи**kwargs(включая произвольные изменяемые объекты) передаются в целевую функцию без изменений. - Если вызов целевой функции завершается исключением, это исключение беспрепятственно всплывает дальше. Новый эталон при этом не устанавливается, а текущий остаётся неизменным.
- При успешном выполнении целевой функции (она вызывается строго один раз за обращение) полученное число проверяется на монотонность.
- Самый первый успешный результат после инициализации декоратора или после вызова
reset_baseline()принимается безоговорочно (без сравнения) и становится текущим эталоном. - Каждый последующий результат принимается только в том случае, если он строго больше текущего эталона. При соблюдении этого условия возвращается исходный числовой объект, а эталон обновляется до этого значения.
- Если результат меньше текущего эталона или равен ему, возбуждается исключение
MonotonicityError(или его подкласс), а прежний эталон остаётся неизменным. - Метод
reset_baseline(self)сбрасывает сохранённый эталон текущего экземпляра без обращения к целевой функции. Следующий успешный вызов функции принимается безоговорочно. Возвращаемое значение дляreset_baseline()не регламентируется.
Каждый задекорированный объект ведёт собственный независимый эталон. Допустимо от 0 до 1000 последовательных вызовов и сбросов на один декоратор; поддержка рекурсивных или повторно входимых вызовов не требуется.
Ввод и вывод
Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля класс верхнего уровня MonotonicChecksum и вызывает его с проверочными аргументами.
Пример использования
@MonotonicChecksum
def checksum(block):
return sum(block)
print(checksum([1, 2]))
try:
checksum([3])
except MonotonicityError:
print('violation')
checksum.reset_baseline()
print(checksum([0]))
Вывод:
3 violation 0
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- Класс-декоратор Python: когда вызывается init
- Класс-декоратор метода Python: почему теряется self
- Класс-декоратор Python: ограничение изменения результата между вызовами
- Класс-декоратор Python: баланс доступных вызовов функции
- Класс-декоратор Python: изменение аргумента первых N вызовов
- Класс-декоратор Python: буфер событий и пакетная запись
