如何实现支持多异常转换的带参数类方法装饰器?
问题
现有类方法evaluate执行时若计算结果过大会抛出OverflowError,可以用overflow_adapter装饰器将其转换为ValueError抛出。现在需要实现一个带参数的exception_adapter装饰器,支持指定需要捕获的异常列表(通过aware参数)以及要抛出的目标异常(通过response参数)。以下是未完成的代码,请补全使其正常工作:
def evaluate(self): return self.left ** self.right
def overflow_adapter(method): def wrapper(self): try: return method(self) except OverflowError: raise ValueError("Result is too big!") return wrapper @overflow_adapter def evaluate(self): return self.left ** self.right
@exception_adapter(aware=[OverflowError,], response=ValueError("Result is too big!")) def evaluate(self): return self.left ** self.right
def exception_adapter(...): def wrapper(...): try: return method(self) except BaseException as e: if e in aware: raise response return wrapper
解答
带参数的装饰器需要三层嵌套结构:外层函数接收装饰器的参数,中层函数接收被装饰的方法,内层是实际执行的包装函数。同时需要修正异常判断的逻辑(直接用e in aware无法正确匹配异常实例和异常类的关系),补全后的代码如下:
def exception_adapter(aware, response): def decorator(method): def wrapper(self, *args, **kwargs): try: return method(self, *args, **kwargs) except BaseException as e: if isinstance(e, tuple(aware)): # 若需要保留原异常上下文,可使用 raise response from e raise response return wrapper return decorator
关键点说明:
- 三层结构:
exception_adapter先接收aware和response参数,返回装饰器函数decorator;decorator接收被装饰的method,返回包装函数wrapper。 - 异常匹配:使用
isinstance(e, tuple(aware))判断异常实例e是否属于aware列表中的任意异常类,这是Python中捕获多异常的标准写法。 - 兼容可变参数:
wrapper中加入*args, **kwargs可以让装饰器适配带额外参数的方法,增强通用性。 - 可选上下文保留:如果需要保留原异常的追踪信息,可以将
raise response改为raise response from e,这样在报错时会显示原异常的触发原因。
使用验证:
# 测试用类 class Calculator: def __init__(self, left, right): self.left = left self.right = right @exception_adapter(aware=[OverflowError,], response=ValueError("Result is too big!")) def evaluate(self): return self.left ** self.right # 触发异常 calc = Calculator(10**100, 10**100) calc.evaluate() # 会抛出 ValueError: Result is too big!
内容的提问来源于stack exchange,提问作者Miłosz Brzechczyn
相关产品推荐
相关产品推荐

