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

配置所需参数后装饰器仍无法识别位置参数的问题排查

问题根源与修复方案

你的装饰器触发TypeError的核心原因:sig.bind(*args, **kwargs)会严格校验原函数的签名——原函数里b是无默认值的必填参数(位于/和*args之间,属于POSITIONAL_OR_KEYWORD类型),调用foo(10, d=22)时缺少b,bind会直接抛出错误,根本走不到后续注入默认值的逻辑。

修复后的完整代码

from functools import wraps
from inspect import signature

def default_args(defaults):
    def decorator(func):
        sig = signature(func)
        # 禁止给仅限位置参数设置默认值
        for param in sig.parameters.values():
            if param.kind == param.POSITIONAL_ONLY and param.name in defaults:
                raise ValueError(f"Parameter {param.name} of function {func.__name__} is positional only and cannot be set by default")
        
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 用bind_partial替代bind,允许部分参数绑定,避免必填参数缺失直接报错
            bound = sig.bind_partial(*args, **kwargs)
            # 注入自定义默认值
            for name, val in defaults.items():
                if name not in bound.arguments:
                    bound.arguments[name] = val
            # 应用原函数自带的默认值(如果未被自定义覆盖)
            bound.apply_defaults()
            return func(*bound.args, **bound.kwargs)
        
        # 更新包装函数的签名,展示正确的默认值
        wrapper.__signature__ = sig.replace(
            parameters=[
                p.replace(default=defaults.get(p.name, p.default)) 
                for p in sig.parameters.values()
            ]
        )
        return wrapper
    return decorator

@default_args({'b': 15, 'd': 17, 'c': 8})
def foo(a, /, b, *args, c=5, d, **kwargs):
    """My Function"""
    print(f"{a=} {b=} {args=} {c=} {d=} {kwargs=}")

# 测试
foo(10, d=22)  # 输出: a=10 b=15 args=() c=8 d=22 kwargs={}
foo(10, 20, d=11)  # 输出: a=10 b=20 args=() c=8 d=11 kwargs={}

关键修改说明

  • 替换bind为bind_partial:bind_partial不强制要求所有必填参数都存在,给我们留了注入默认值的空间。
  • 添加bound.apply_defaults():确保原函数自带的默认值(比如c原本的5)在未被自定义覆盖时能正常生效。
  • 修正函数名引用:原代码里的func.name是错误的,应该用func.__name__来获取函数名。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 12:50:41