如何将try-except-else移至装饰器并避免使用全局变量?
无全局变量实现C类实例的异常与收尾逻辑复用
问题背景
原业务脚本通过try-except-else逻辑处理C类实例的异常捕获与收尾操作,但这段逻辑在每个脚本中重复编写冗余度高。尝试用装饰器提取逻辑时,仅能通过全局变量传递实例,现需在不依赖全局变量的前提下完成逻辑复用。
原模板代码:
from shared import C def do(ins): ins.x() def main(): try: ins = C(1,'a') do(ins) except: ins.handle() else: ins.finalize() if __name__ == '__main__': main()
最初的装饰器实现(依赖全局变量才能工作):
from functools import wraps def dec(ins): def a(f): @wraps(f) def b(*a, **k): try: f(*a, **k) except: ins.handle() else: ins.finalize() return b return a
解决方案
方案1:改进装饰器,内部创建实例
修改shared.py中的装饰器,让它接收C类的构造参数,在装饰器内部完成实例初始化、业务执行、异常处理与收尾操作:
from functools import wraps from . import C # 根据实际路径调整导入 def dec(*c_args, **c_kwargs): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): # 内部创建C类实例 ins = C(*c_args, **c_kwargs) try: # 将实例传入业务函数 func(ins, *args, **kwargs) except: ins.handle() else: ins.finalize() return wrapper return decorator
业务脚本中使用方式:
from shared import dec def do(ins): ins.x() # 直接传入C类的构造参数,无需全局变量 @dec(1, 'a') def main(ins): do(ins) if __name__ == '__main__': main()
方案2:使用上下文管理器(更符合Pythonic风格)
对于这种"初始化-执行-收尾/异常处理"的场景,上下文管理器的语义更清晰,在shared.py中实现:
from contextlib import contextmanager from . import C @contextmanager def c_context(*args, **kwargs): ins = C(*args, **kwargs) try: # 将实例交给业务代码使用 yield ins except: ins.handle() # 若需要将异常向上抛出,取消下方注释 # raise else: ins.finalize()
业务脚本中使用方式:
from shared import c_context def do(ins): ins.x() def main(): # 上下文自动处理实例的异常与收尾 with c_context(1, 'a') as ins: do(ins) if __name__ == '__main__': main()
内容的提问来源于stack exchange,提问作者user17135505
相关产品推荐
相关产品推荐

