Генератор скользящего среднего на Python со сбросом окна
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Генераторы Python: задачи на ленивые конвейеры и закрытие ресурсов.
Сглаживающий фильтр со сбросом
Потоковый фильтр принимает из внешнего источника числовые замеры вибрации и сглаживает колебания скользящим окном фиксированной длины . Пока в буфере не накопится ровно значений, фильтр ничего не отдает наружу. Как только окно заполнится, он начинает выдавать среднее арифметическое на каждом новом шаге.
Поток данных может прерываться служебными метками. Встретив строковый маркер 'RESET', фильтр полностью очищает накопленное окно и выдает единственное число 0.0 независимо от того, сколько замеров было собрано к этой секунде. После этого сбор окна начинается заново по тем же правилам.
Если входной поток исчерпался либо внешний потребитель досрочно закрыл сам фильтр через close(), блок finally гарантированно вызывает close() у нижележащего источника. Если же фильтр закрыли еще до первого обращения к нему, его тело не начинает выполняться и входящий генератор остается нетронутым.
Реализуйте генератор скользящего окна, который выдает среднее только для заполненных окон, возвращает ноль при сбросе и аккуратно закрывает источник замеров при любом завершении работы.
Что уже дано
В среде исполнения доступны вспомогательные функции make_telemetry_source и observe_reset_generator, моделирующие и отслеживающие поведение источников и генераторов. В заготовке решения объявлена функция-генератор resettable_window(source, width), тело которой вам предстоит реализовать.
Что нужно сделать
Реализуйте функцию resettable_window(source, width).
Параметры функции:
source— однократный итерируемый источник элементов (от 0 до 1000 записей в тестовых последовательностях), выдающий конечные числаintиfloatв диапазоне от -1 000 000 до 1 000 000, а также строковые токены'RESET'. Объект имеет методclose(), вызов которого гарантированно не выбрасывает исключений. Чтение изsourceможет прерываться ошибками;width— целое число от 1 до 128, задающее размер скользящего окна ().
Функция должна возвращать нативный генератор Python со следующим поведением:
- Вызов
resettable_window(source, width)возвращает незапущенный генератор: создание генератора или его вызовclose()до первого обращенияnext()не производят чтений изsourceи не вызываютsource.close(). - Чтение из
sourceвыполняется строго по требованию (on demand) до получения очередного значения: нельзя считывать элементы наперёд дальше, чем необходимо для отдачи следующего результата окна или сброса. - Пока с момента старта или последнего сброса не получено хотя бы
widthчисловых замеров, частичные средние не генерируются. - Как только накопилось
widthчисловых замеров, каждый последующий числовой замер выдаёт черезyieldсреднее арифметическое последнихwidthчисловых значений в виде числа с плавающей точкойfloat. - Каждый встреченный маркер
'RESET'очищает все накопленные данные текущего окна и выдаёт черезyieldровно одно значение0.0. Это правило действует в том числе для нескольких маркеров'RESET'подряд или маркеров, встреченных до накопления полного окна. - При штатном исчерпании источника, возникновении ошибки чтения из
source, передаче исключения от потребителя черезthrow()в запущенный генератор или досрочном закрытии черезclose()запущенного генератора методsource.close()должен быть вызван ровно один раз в блокеfinally. - Запрещено выполнять
yieldвнутри финализации (при обработке закрытия генератора). - Генератор, приостановленный после выдачи очередного значения, ещё не знает об исчерпании источника;
source.close()вызывается, когда генератор возобновляется до конца потока либо закрывается явно. - Ошибки источника или потребителя должны беспрепятственно всплывать дальше, если закрытие
source.close()прошло успешно. Никакой дополнительной валидации входных типов реализовывать не требуется.
Ввод и вывод
Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля функцию верхнего уровня resettable_window и вызывает её с проверочными аргументами.
Пример использования
source = make_telemetry_source([1, 3, 5, 'RESET', 4, 8])
print(list(resettable_window(source, 2)))
print(source.close_calls)
Вывод:
[2.0, 4.0, 0.0, 6.0]
1
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- GeneratorExit и yield при close(): вопрос по генераторам Python
- Генераторы Python: синхронизация потоков после фильтрации
- Генераторы Python: разделите поток между двумя потребителями
- Исправьте остановку генераторного конвейера Python
- Генераторы Python: закройте второй источник при ошибке первого
- Фильтрация потока Python: исключения и гарантированное закрытие генератора
