You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不修改源码的前提下为已装饰Python函数插入新装饰器?

带参装饰器的提取与堆叠实现方案

核心问题解答

1. 能否直接从func1提取my_dec1到变量?

不能直接提取。带参装饰器@my_dec1(a,b)的执行逻辑是:先调用my_dec1(a,b)返回一个实际的装饰器函数,再用这个函数去装饰func1。被装饰后的func1仅保留了最终的包装函数引用,不会直接存储原my_dec1的入口引用,除非装饰器实现时特意将自身信息绑定到了函数属性中。

2. 能否提取my_dec1的参数以重建装饰器?

可以尝试,但依赖装饰器的实现方式:

  • 自定义属性存储参数:如果my_dec1在实现时,将a、b存入了包装函数的自定义属性(比如func.__dec_args__ = (a, b)),可直接读取该属性获取参数。
  • 解析闭包变量:带参装饰器的参数通常会保存在闭包中,可通过inspect模块解析闭包变量来提取参数。示例代码:
    import inspect
    
    def extract_dec_args(target_func):
        current = target_func
        while hasattr(current, '__wrapped__'):
            closure_info = inspect.getclosurevars(current)
            # 需根据my_dec1实际的参数名调整判断条件
            if 'a' in closure_info.nonlocals and 'b' in closure_info.nonlocals:
                return closure_info.nonlocals['a'], closure_info.nonlocals['b']
            current = current.__wrapped__
        return None, None
    
    # 执行逻辑
    original_func = func1.__wrapped__
    dec_a, dec_b = extract_dec_args(func1)
    if dec_a is not None and dec_b is not None:
        # 实现目标堆叠:先my_dec2装饰原函数,再用my_dec1(a,b)装饰
        final_func = my_dec1(dec_a, dec_b)(my_dec2(original_func))
    
    注意:该方法需要匹配my_dec1闭包中实际的参数变量名,若装饰器基于类实现,闭包结构会不同,需针对性调整。

最终实现逻辑

你已经通过func1.__wrapped__获取了解装饰后的原函数,只要成功提取到a、b,就可以通过my_dec1(a,b)(my_dec2(原函数))的调用顺序,实现与@my_dec1(a,b)、@my_dec2依次装饰原函数完全等价的效果。

内容的提问来源于stack exchange,提问作者Benjamin Chew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 10:27:18