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

如何在不使用inspect模块的情况下移除函数签名中的绑定参数?

不使用inspect模块移除函数默认参数的实现方案

核心思路

避开修改函数元数据的方式,通过动态生成仅接受必填参数的包装函数解决问题:先利用Python调用函数时的错误提示,提取绑定指定参数后剩余的必填参数,再通过exec生成签名匹配的包装器,内部调用绑定后的原函数。

实现代码

from functools import partial

def _get_required_args(func):
    try:
        func()
    except TypeError as err:
        err_msg = str(err)
        # 处理单个必填参数的场景
        if "required positional argument" in err_msg:
            return [err_msg.split("'")[1]]
        # 处理多个必填参数的场景
        elif "required positional arguments" in err_msg:
            # 从错误信息中解析出参数名
            arg_parts = err_msg.split("'")
            return [arg_parts[i] for i in range(1, len(arg_parts), 2)]
    return []

def remove_default_args(func, **kwargs):
    # 先绑定用户指定的参数到原函数
    bound_func = partial(func, **kwargs)
    # 获取绑定后函数的必填参数列表
    required_args = _get_required_args(bound_func)
    # 动态生成仅接受必填参数的包装函数代码
    wrapper_code = f"""
def wrapper({', '.join(required_args)}):
    return bound_func({', '.join(required_args)})
"""
    local_namespace = {}
    # 执行代码生成包装函数
    exec(wrapper_code, {"bound_func": bound_func}, local_namespace)
    return local_namespace["wrapper"]

使用示例

假设外部库的函数如下:

# 模拟外部库带默认参数的函数
def bar1(a, b=10, c=20):
    return a + b + c

def bar2(x, y="hello", z=True):
    return f"{x}-{y}-{z}"

使用包装函数适配:

# 直接包装,保留原函数必填参数
wrapped_bar1 = remove_default_args(bar1)
print(wrapped_bar1(5))  # 输出:35(5+10+20)

# 绑定部分参数后包装,仅剩余必填参数
wrapped_bar1_custom = remove_default_args(bar1, b=5)
print(wrapped_bar1_custom(5))  # 输出:30(5+5+20)

# 适配另一个外部函数
wrapped_bar2 = remove_default_args(bar2)
print(wrapped_bar2("test"))  # 输出:test-hello-True

这个方案完全不需要依赖inspect模块,生成的包装函数签名仅包含必填参数,能直接满足foo的调用要求,同时批量处理100个外部函数也非常方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 14:02:55