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

如何包装函数以保证__code__.co_argcount参数数量准确?

解决高阶函数检查__code__.co_argcount导致包装函数失效的问题

问题核心

你遇到的问题是:用functools.wraps包装后的函数,因内部使用*args, **kwargs,导致__code__.co_argcount为0,而目标API的高阶函数会直接检查这个只读属性,拒绝不符合参数数量要求的函数,且无法修改API或进行猴子补丁。

解决方案:用可调用类代理属性

我们可以创建一个可调用类实现包装逻辑,通过代理__code__属性到原函数,让高阶函数检查时拿到原函数的参数数量,同时保留包装功能。这种方法适配任意参数数量需求,无需修改目标API。

实现代码

import functools

class FunctionWrapper:
    def __init__(self, func):
        self.func = func
        # 复制原函数的元数据(名称、文档、模块等)
        functools.update_wrapper(self, func)
    
    def __call__(self, *args, **kwargs):
        # 这里添加你的包装逻辑
        print("wrapped1!")
        result = self.func(*args, **kwargs)
        print("wrapped2!")
        return result
    
    @property
    def __code__(self):
        # 代理原函数的__code__属性,让高阶函数拿到原函数的参数数量
        return self.func.__code__

# 用这个类作为装饰器
def my_wrapper(func):
    return FunctionWrapper(func)

# 原函数
def original(a, b, c):
    return None

wrapped = my_wrapper(original)

# 测试调用
high_order_function(original)  # 正常通过
high_order_function(wrapped)   # 现在也能正常通过
wrapped(1, 2, 3)               # 包装逻辑正常执行

方案有效性说明

  1. 属性代理:通过@property装饰的__code__方法,让包装对象的__code__指向原函数的__code__,高阶函数检查co_argcount时会得到原函数的参数数量,符合要求。
  2. 可调用对象:类实现了__call__方法,实例可像普通函数一样被调用,内部通过*args, **kwargs兼容任意参数,保证包装逻辑正常执行。
  3. 元数据保留:functools.update_wrapper复制原函数的名称、文档字符串、模块等元数据,避免因元数据不一致导致的其他问题。

备选方案:动态生成匹配参数的包装函数

如果不想用类,也可以通过动态代码生成,创建和原函数参数数量完全匹配的包装函数。这种方法无需代理属性,但代码复杂度较高:

import functools

def my_wrapper(func):
    arg_count = func.__code__.co_argcount
    # 生成参数列表字符串,比如"a,b,c"
    args_str = ",".join([f"arg{i}" for i in range(arg_count)])
    # 动态定义包装函数
    exec(f"""
@functools.wraps(func)
def inner({args_str}, **kwargs):
    print("wrapped1!")
    result = func({args_str}, **kwargs)
    print("wrapped2!")
    return result
""")
    return locals()["inner"]

该方法需要处理可变参数、关键字参数等复杂场景,通用性和可维护性不如可调用类方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:42:22