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

如何创建可为函数添加参数的装饰器?支持默认值与inspect兼容吗?

如何实现为函数添加参数的装饰器

完全可以实现这类装饰器——既能给函数新增带默认值的参数,又能保证原有函数行为不变,同时让inspect模块能识别到新增的参数。下面是具体实现方案:

核心思路

要达成需求,需要完成两个关键操作:

  1. 修改函数的签名信息,让inspect能检测到新增的参数
  2. 包装原函数,确保新增参数不会干扰原函数的正常执行逻辑

具体实现代码

import inspect
import functools

def add_argument(name, default=None):
    def decorator(func):
        # 获取原函数的签名对象
        orig_signature = inspect.signature(func)
        # 构造新增的参数对象,默认设为位置/关键字参数类型
        new_param = inspect.Parameter(
            name,
            kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
            default=default
        )
        # 合并原参数与新参数,生成新签名
        new_params = list(orig_signature.parameters.values()) + [new_param]
        new_signature = orig_signature.replace(parameters=new_params)

        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # 仅绑定原函数需要的参数,自动忽略新增的参数
            bound_args = orig_signature.bind(*args, **kwargs)
            bound_args.apply_defaults()
            # 调用原函数并返回结果
            return func(*bound_args.args, **bound_args.kwargs)
        
        # 给包装后的函数设置新的签名,让inspect能识别
        wrapper.__signature__ = new_signature
        return wrapper
    return decorator

测试验证

@add_argument('bob', default=None)
def simple(a, b):
    return a + b

# 检查函数签名
import inspect
print(inspect.signature(simple))
# 输出:<Signature (a, b, bob=None)>

# 验证原有调用逻辑不受影响
print(simple(1, 2))  # 输出:3
# 验证带新增参数的调用也能正常执行
print(simple(1, 2, bob="hello"))  # 输出:3
print(simple(1, 2, bob=100))  # 输出:3

关键细节说明

  • 使用functools.wraps保留原函数的元信息(函数名、文档字符串等),避免装饰器破坏原函数的标识
  • 通过inspect.Parameter构造参数对象,支持指定参数类型(比如如果要让新增参数只能通过关键字传递,可把kind设为inspect.Parameter.KEYWORD_ONLY)
  • 利用orig_signature.bind严格绑定原函数的参数,确保新增参数不会被传入原函数,完全不影响原有逻辑
  • 如果需要避免参数名冲突,可以在装饰器里加个判断:检查新增参数名是否已存在于原函数的参数列表中,若存在则抛出异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 20:15:37