如何实现共享内部逻辑、仅内置flag不同的两个Python参数化装饰器
问题原因
你原来的实现里_decorator没有接收args_units和kwargs_units作为入参,两个工厂函数也没有把收到的units参数绑定到_decorator的调用上下文里,因此_wrapper里访问这两个变量时会触发作用域查找失败。
修复方案1:沿用partial思路调整参数顺序
把units参数、flag都作为_decorator的前置入参,工厂函数接收用户传入的units后,和固定flag一起绑定到偏函数中即可:
import functools # 公共装饰器逻辑,按顺序接收units参数、flag、被装饰函数 def _decorator(args_units, kwargs_units, flag, func): @functools.wraps(func) def _wrapper(*args, **kwargs): if flag: return f1(*args, **kwargs, *args_units, **kwargs_units) else: return f2(*args, **kwargs, *args_units, **kwargs_units) return _wrapper def decorator_factory1(*args_units, **kwargs_units): # 绑定前三个参数,返回仅需接收func的偏函数 return functools.partial(_decorator, args_units, kwargs_units, True) def decorator_factory2(*args_units, **kwargs_units): return functools.partial(_decorator, args_units, kwargs_units, False)
该方案完全兼容你预期的装饰器使用方式,不需要调整调用逻辑。
修复方案2:用闭包生成装饰器工厂(更简洁)
如果不需要显式用partial,可以直接写一个高阶函数生成两个工厂,复用所有逻辑:
import functools def _create_decorator_factory(flag): # 接收flag返回对应装饰器工厂 def decorator_factory(*args_units, **kwargs_units): def _decorator(func): @functools.wraps(func) def _wrapper(*args, **kwargs): if flag: return f1(*args, **kwargs, *args_units, **kwargs_units) else: return f2(*args, **kwargs, *args_units, **kwargs_units) return _decorator return _decorator return decorator_factory # 一次性生成两个对外暴露的装饰器工厂 decorator_factory1 = _create_decorator_factory(flag=True) decorator_factory2 = _create_decorator_factory(flag=False)
该方案通过闭包直接捕获flag值,没有额外的partial调用,逻辑更直观,后续要新增更多flag对应的装饰器工厂时只需要加一行赋值即可。
内容的提问来源于stack exchange,提问作者ThomasNicholas
相关产品推荐
相关产品推荐

