如何创建可为函数添加参数的装饰器?支持默认值与inspect兼容吗?
如何实现为函数添加参数的装饰器
完全可以实现这类装饰器——既能给函数新增带默认值的参数,又能保证原有函数行为不变,同时让inspect模块能识别到新增的参数。下面是具体实现方案:
核心思路
要达成需求,需要完成两个关键操作:
- 修改函数的签名信息,让
inspect能检测到新增的参数 - 包装原函数,确保新增参数不会干扰原函数的正常执行逻辑
具体实现代码
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
相关产品推荐
相关产品推荐

