有人能解释一下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中是如何工作的吗的主要内容,如果未能解决你的问题,请参考以下文章