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

如何按原函数参数定义顺序处理Python装饰器包装的函数参数?

解决方案

直接使用Python标准库inspect模块的签名绑定能力,无需手动匹配位置参数和关键字参数,即可获取和原函数参数定义顺序完全一致的完整参数字典。

核心逻辑是调用inspect.signature(func).bind(*args, **kwargs),该方法会按照原函数的参数定义规则,将传入的位置参数、关键字参数一一匹配,返回的绑定对象的.arguments属性是一个有序字典:键为参数名,值为传入的参数值,顺序和函数定义时的参数顺序完全一致,不受实际传参方式影响。
如果需要将未显式传入的默认参数也纳入结果,可以额外调用绑定对象的apply_defaults()方法。

修正后的装饰器实现

import inspect

def wrapper(func):
    # 提前解析原函数签名,避免每次调用重复解析损耗性能
    sig = inspect.signature(func)
    def f(*args, **kwargs):
        # 将传入参数绑定到原函数签名
        bound_args = sig.bind(*args, **kwargs)
        # 可选操作:自动填充未显式传入的默认参数值
        bound_args.apply_defaults()
        # 获取顺序与原函数定义完全一致的参数字典
        all_params = bound_args.arguments
        
        # 此时按values取值的类型顺序永远和参数定义顺序一致
        print([type(v) for v in all_params.values()])
        return func(*args, **kwargs)
    return f

@wrapper
def foo(a, b, c, d):
    print(f"{a} {b} {c} {d}")

foo(10, 12.5, 14, 5.2)
foo(10, 12.5, d=5.2, c=14)

运行结果

两次调用打印的类型列表完全一致,符合预期:

[<class 'int'>, <class 'float'>, <class 'int'>, <class 'float'>]
10 12.5 14 5.2
[<class 'int'>, <class 'float'>, <class 'int'>, <class 'float'>]
10 12.5 14 5.2

方案优势

  • 兼容所有合法Python函数传参形式:全位置传参、全关键字传参、位置+关键字混合传参、带默认值参数、*args可变位置参数、**kwargs可变关键字参数、仅限关键字参数都能正确匹配
  • 传参不合法时会自动抛出和原函数调用完全一致的TypeError,不会改变原函数的原有行为
  • 无需手动编写参数匹配逻辑,参数重名、位置参数溢出等边界情况均由标准库统一处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 00:27:19