有人可以解释一下staticmethod的源代码如何在python中工作

use*_*759 15 python static-methods decorator python-internals python-decorators

首先,我理解一般来说装饰工作是如何工作的.而且我知道@staticmethod在签名中剥离实例参数

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

有效.

但是,我不明白如何staticmethod实现这一点的源代码.

在我看来,该包装方法时foostaticmethod,实例staticmethod被实例化,那么一些神奇的发生,使C.foo()合法的.

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

我知道关于SO的巨大话题,staticmethods但没有一个能解决我的疑虑.但也许我没有点击魔术关键词.如果是的话,请告诉我.

对于寻找staticmethod源代码的人,请参阅https://hg.python.org/cpython/file/c6880edaf6f3/Objects/funcobject.c

Mar*_*ers 15

staticmethod对象是一个描述符.您缺少的魔力是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对象在C代码中定义,但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
Run Code Online (Sandbox Code Playgroud)

self.f原始包装功能在哪里.

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

还有一个classmethod,它使用第二个参数descriptor.__get__将函数绑定到类,然后有property对象,它们直接将绑定转换为函数调用.请参阅@property装饰器如何工作?.