Класс-декоратор Python: переключение источника после ошибки
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Классы-декораторы Python: задачи на call, методы и состояние.
Резервное питание прибора
Лабораторный прибор выполняет серию замеров и связывается с силовой шиной через функцию опроса, принимающую именованный параметр источника питания line. В штатном режиме обращения направляются в основную сеть со значением line="grid". За непрерывностью работы следит управляющий декоратор, удерживающий текущее состояние линии.
Если при обращении к основной сети возникает сетевой сбой ConnectionError, декоратор перехватывает эту ошибку, переводит внутренний тумблер на резервную батарею (line="battery") и сразу повторяет замер ровно один раз уже с новым источником. Все последующие замеры прибор продолжает выполнять исключительно от батареи, не предпринимая попыток вернуться к сети самостоятельно, пока оператор не выполнит явный сброс вызовом метода restore_grid().
Любые другие неполадки вроде неверных аргументов ValueError не влияют на положение тумблера и сразу пробрасываются вызывающему коду. Точно так же наружу передаются любые сбои при работе от батареи, включая неудачу повторного вызова после переключения.
Реализуйте класс-декоратор, который избирательно реагирует на сетевой сбой основной линии мгновенным переходом на резервную батарею, повторяет замер ровно один раз и сохраняет аварийный режим до явного восстановления.
Что уже дано
В редакторе представлена заготовка класса-декоратора BackupPower с методами __init__, __call__ и restore_grid. Во время тестирования доступна вспомогательная функция наблюдения observe_backup_power, реализовывать которую не требуется.
Что нужно сделать
Реализуйте класс-декоратор BackupPower.
Конструктор __init__(self, func) принимает целевую синхронную функцию func, которая помимо аргументов вызывающей стороны принимает строго именованный параметр line (line="grid" или line="battery").
Экземпляр класса должен поддерживать вызов __call__(self, *args, **kwargs) и метод сброса restore_grid(self):
- Начальное состояние каждого экземпляра декоратора — основная сеть (
"grid"). Экземпляры декоратора независимы друг от друга и сохраняют собственное состояние линии. - Вызывающий код передаёт любые позиционные и именованные аргументы (
*args,**kwargs), сохраняя их идентичность. Параметрlineзарезервирован за декоратором и вызывающей стороной не передаётся. - При работе от сети вызывается целевая функция с переданными аргументами и
line="grid". - Только ошибки семейства
ConnectionError(включая любые их подклассы), возникшие при вызове сline="grid", переводят внутреннее состояние линии на батарею ("battery"). Переключение линии происходит до выполнения повторного вызова. Сразу после переключения декоратор выполняет ровно одну попытку повторного вызова сline="battery"и теми же аргументами. - Любые другие исключения (включая другие подклассы
ExceptionилиBaseException), возникшие при работе от сети, не меняют состояние линии (остаётся"grid") и сразу пробрасываются вызывающему коду без повторного вызова. - Если декоратор уже находится в режиме батареи, целевая функция вызывается один раз с
line="battery". Любая ошибка при вызове от батареи (в том числе при единственной повторной попытке сразу после переключения) немедленно пробрасывается наружу без повторных попыток. - После перехода на батарею все последующие вызовы продолжают выполняться с
line="battery", пока не будет вызван методrestore_grid(). - Метод
restore_grid()сбрасывает состояние линии текущего экземпляра обратно на"grid". Метод не вызывает целевую функцию и не обязан возвращать значение. - При успешном выполнении целевой функции возвращается её оригинальный результат (включая ложные значения
None,False,0и изменяемые объекты).
Ввод и вывод
Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля класс верхнего уровня BackupPower и вызывает его с проверочными аргументами.
Пример использования
attempts = []
@BackupPower
def measure(*, line):
attempts.append(line)
if len(attempts) == 1:
raise ConnectionError('grid unavailable')
return line
print(measure())
print(measure())
measure.restore_grid()
print(measure())
print(attempts)
Вывод:
battery
battery
grid
['grid', 'battery', 'battery', 'grid']
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- Класс-декоратор Python: когда вызывается init
- Класс-декоратор метода Python: почему теряется self
- Класс-декоратор Python: ограничение изменения результата между вызовами
- Класс-декоратор Python: баланс доступных вызовов функции
- Класс-декоратор Python: изменение аргумента первых N вызовов
- Класс-декоратор Python: буфер событий и пакетная запись
