有人能解释一下staticmethod的源代码在python中是如何工作的吗

Posted

技术标签:

【中文标题】有人能解释一下staticmethod的源代码在python中是如何工作的吗【英文标题】:Can someone explain how the source code of staticmethod works in python 【发布时间】:2015-11-02 03:50:53 【问题描述】:

首先,我了解装饰器的工作原理。我知道@staticmethod 去掉了签名中的实例参数,使得

class C(object):
    @staticmethod
    def foo():
        print 'foo'
C.foo    //<function foo at 0x10efd4050>
C().foo  //<function foo at 0x10efd4050>

有效。

但是,我不明白 staticmethod 的源代码是如何做到这一点的。

在我看来,当在 staticmethod 中包装方法 foo 时,staticmethod 的实例被实例化,然后 一些魔法 发生了,使 C.foo() 合法。

那么.. 那些魔法会发生什么? staticmethod 做了什么?

我知道关于staticmethods 的大量话题,但没有一个能解决我的疑虑。但也许我没有击中魔法关键字。如果是这样,请告诉我。

寻找staticmethod源代码的朋友请参考https://hg.python.org/cpython/file/c6880edaf6f3/Objects/funcobject.c

【问题讨论】:

【参考方案1】:

staticmethod 对象是descriptor。您缺少的神奇之处在于 Python 在将对象作为类或实例的属性访问时调用了 __get__ 方法。

因此以C.foo 访问对象会导致Python 将其转换为C.__dict__['foo'].__get__(None, C),而instance_of_C.foo 则变为type(instace_of_C).__dict__['foo'].__get__(instance_of_C, type(instance_of_C))

staticmethod 对象是 defined in C code,但 Python 中的等价物是:

class staticmethod(object):
    def __init__(self, callable):
        self.f = callable
    def __get__(self, obj, type=None):
        return self.f
    @property
    def __func__(self):
        return self.f

self.f 是原始包装函数。

所有这些都是必需的,因为函数本身也是描述符;它是为您提供方法对象的描述符协议(有关详细信息,请参阅python bound and unbound method object)。由于它们也有 __get__ 方法,但没有 staticmethod 对象包装函数,因此 functionobj.__get__ 调用会生成一个方法对象,并传入 self 参数。

还有一个classmethod,它使用descriptor.__get__的第二个参数将一个函数绑定到类,然后还有property对象,将绑定直接转化为函数调用。见How does the @property decorator work?。

【讨论】:

我从 PyCharm IDE 得到源代码..我不知道它是否是真正的副本..oops @user2829759:PyCharm 无法访问实际的源代码(因为它是编译的 C 代码),因此它会通过自省对象为您重建一个 shim。 @martijinpieters 是否反映了 C 代码中正在发生的事情? @user2829759:我的 Python 代码版本?绝对地。 PyCharm 反射无法显示在方法中发生了什么,它只能推断出一个签名。 @user2829759:但是,__func__ 属性描述是完全错误的。它只是简单地返回被包装的函数(就像__get__ 方法一样,基本上)。 __getattribute____new__ 方法的存在只是令人困惑的事情。

以上是关于有人能解释一下staticmethod的源代码在python中是如何工作的吗的主要内容,如果未能解决你的问题,请参考以下文章

递归函数:有人能解释一下这段代码是如何打印 1 到 5 的吗?

有人能帮解释一下下面的C语言代码吗?主要是指针

PHP 语法 ??意思,有人能解释一下吗? [复制]

有人能解释一下这个功能吗

有人能解释一下猪的这个奇怪的错误吗

我的代码出错了,谁能解释一下怎么回事?