Python中如何用装饰器处理AssertionError替代嵌套try/except块
实现方案
你遇到的NameError是因为装饰器在函数定义阶段就会执行,此时函数的参数x、y还未被初始化,自然无法识别。我们可以通过带参数的装饰器工厂实现你要的效果,完全替代嵌套的try/except块,以下是可直接运行的完整代码:
完整实现代码
# 断言异常捕获装饰器:捕获校验函数抛出的AssertionError,打印错误并返回校验结果 def catch_assert(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except AssertionError as exc: print(exc) return False return wrapper # 自定义校验规则,用catch_assert装饰自动处理异常 @catch_assert def is_int(x): assert isinstance(x, int), f"'{x}' is not an integer" return True @catch_assert def is_str(y): assert isinstance(y, str), f"'{y}' is not a string" return True # 校验装饰器工厂:传入要校验的参数名、对应的校验函数,返回实际装饰器 def validate(param_name: str, check_func): def decorator(func): def wrapper(*args, **kwargs): # 自动映射参数名和传入的参数值,兼容位置参数、关键字参数 import inspect func_sig = inspect.signature(func) bound_args = func_sig.bind(*args, **kwargs) bound_args.apply_defaults() target_value = bound_args.arguments[param_name] # 校验失败直接终止执行,校验通过才运行后续逻辑 if not check_func(target_value): return return func(*args, **kwargs) return wrapper return decorator # 装饰目标函数,装饰器从下到上执行,先校验y再校验x @validate("x", is_int) @validate("y", is_str) def pretty_function(x: int, y: str): print(f'There is/are {x} {y}')
测试运行
pretty_function(2,'cat') pretty_function(2,3) pretty_function('2','cat')
输出结果
There is/are 2 cat '3' is not a string '2' is not an integer
逻辑说明
- 你之前写的
test_assertion存在逻辑冗余:else分支重复执行了一次被装饰函数,优化后仅执行一次,校验成功返回结果、失败返回False validate作为装饰器工厂,在函数定义阶段仅接收配置(参数名、校验规则),实际校验逻辑推迟到函数调用时执行,避免了参数未定义的报错- 新增校验规则仅需要编写对应加了
@catch_assert的校验函数,再给目标函数加一层@validate(参数名, 新校验函数)即可,无需嵌套异常处理块,可读性极强
内容的提问来源于stack exchange,提问作者Claire Boitet
相关产品推荐
相关产品推荐

