Декоратор, вызывающий колбэки при возникновении заданных исключений

Используйте пары из класса исключения и callback. Первое подходящее правило обрабатывает ошибку; неизвестные исключения пробрасываются.

Короткий ответ

Что ответить на собеседовании

Используйте пары из класса исключения и callback. Первое подходящее правило обрабатывает ошибку; неизвестные исключения пробрасываются.

Подробный разбор

Ответ с пояснениями

Условие

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

def exception_handler(pairs: list[tuple[Exception, Callable[[], None]]]):
    ...

Ответ

Используйте пары из класса исключения и callback. Первое подходящее правило обрабатывает ошибку; неизвестные исключения пробрасываются.

from functools import wraps
from typing import Callable

def exception_handler(pairs: list[tuple[type[Exception], Callable[[], None]]]):
    rules = tuple(pairs)
    def decorate(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as error:
                for kind, callback in rules:
                    if isinstance(error, kind):
                        callback()
                        return None
                raise
        return wrapper
    return decorate

В этом варианте совпавшая ошибка подавляется после callback, результат — None. Если требуется только уведомление с сохранением ошибки, после callback нужен raise. Более специфичные типы ставьте раньше базовых. Исключение внутри самого callback распространяется наружу; его нельзя бесконечно обрабатывать тем же правилом.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее