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

类方法使用inspect.signature时,直接调用与装饰器内调用的Signature.bind().arguments结果差异问题

类方法使用inspect.signature时,直接调用与装饰器内调用的Signature.bind().arguments结果差异问题

这是个非常典型的Python装饰器与描述器(classmethod本质是描述器)交互的问题,核心在于装饰器应用顺序和**classmethod对函数签名的隐式调整**,我来一步步帮你理清:

1. 装饰器中拿到的是原始的未被classmethod处理的函数

先看你代码里的装饰器顺序:

@classmethod
@decorator
def mymethod(cls, a, b): 
    return a + b

Python的装饰器是从下往上执行的:先执行@decorator装饰原始的mymethod函数(这个函数的签名是(cls, a, b)),得到inner函数;再执行@classmethod装饰inner,把它转换成类方法。

所以在装饰器的inner函数里:

  • func变量指向的是原始的未绑定函数(包含cls参数的那个)
  • 当你调用MyClass.mymethod(1,2)时,classmethod会自动把MyClass作为第一个参数传递给inner,也就是说inner收到的*args实际是(MyClass, 1, 2)
  • 用这个参数列表去绑定原始函数的签名(cls, a, b),自然就得到了包含cls的完整参数映射:{'cls': <class '__main__.MyClass'>, 'a': 1, 'b': 2}

2. 直接访问MyClass.mymethod得到的是经过classmethod处理的绑定方法

当你直接写MyClass.mymethod时,拿到的不是原始函数,而是classmethod这个描述器返回的绑定了类的可调用对象。这个对象的签名已经被classmethod隐式调整了:

  • 它会自动把当前类作为第一个参数注入到底层函数中
  • 对外暴露的签名只保留业务参数a和b,不需要你手动传递cls

这就解释了两个现象:

  • inspect.signature(MyClass.mymethod).bind(1, 2)能成功,返回{'a': 1, 'b': 2}——因为签名里已经没有cls参数了
  • inspect.signature(MyClass.mymethod).bind(MyClass, 1, 2)报错“参数过多”——因为这个绑定方法的签名只接受2个位置参数,你多传了一个MyClass

3. 验证结论的小实验

如果你想在外部拿到和装饰器内一致的签名结果,可以通过函数的__wrapped__属性逐层获取原始函数(因为经过了两层装饰:classmethod和decorator):

import inspect
import functools

def decorator(func):     
    @functools.wraps(func)
    def inner(*args, **kwargs): 
        print(inspect.signature(func).bind(*args, **kwargs).arguments)
        return func(*args, **kwargs)
    return inner

class MyClass: 
    @classmethod
    @decorator
    def mymethod(cls, a, b): 
        return a + b

# 逐层获取原始函数
original_func = MyClass.mymethod.__wrapped__.__wrapped__
# 用原始函数签名绑定参数
print(inspect.signature(original_func).bind(MyClass, 1, 2).arguments)
# 输出: {'cls': <class '__main__.MyClass'>, 'a': 1, 'b': 2}

总结

  • 装饰器内部的func是原始未被classmethod处理的函数,签名包含cls,且classmethod会自动注入类作为第一个参数,所以绑定结果包含cls
  • 直接访问的MyClass.mymethod是**classmethod生成的绑定方法**,签名已隐式隐藏cls,只需要传递业务参数

备注:内容来源于stack exchange,提问作者cmsommerville

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 19:09:36