staticmethod 对象描述的含义?

Meaning of staticmethod object's description?

我在实践中了解 @staticmethod 装饰器。但是模拟静态方法的一个错误让我陷入了 Python 语义兔子洞。 The standard type hierarchy 部分中的描述让我感到困惑:

Static method objects provide a way of defeating the transformation of function objects to method objects described above. A static method object is a wrapper around any other object, usually a user-defined method object. When a static method object is retrieved from a class or a class instance, the object actually returned is the wrapped object, which is not subject to any further transformation. Static method objects are not themselves callable, although the objects they wrap usually are. Static method objects are created by the built-in staticmethod() constructor.

staticmethod() 构造函数将函数对象作为唯一参数。它如何包装函数对象以外的任何其他对象?即使这没有失败,它有什么意义?

它通常是如何包装用户定义的方法对象而不是函数对象的?用户定义的方法对象,在调用时,将调用它们的对象添加到参数列表的开头,然后调用存储在 class 上的函数对象(忽略所有各种特殊情况)。

为什么静态方法对象本身是不可调用的?那么,如何调用这些工作呢?

你可以看到staticmethod可以接受任何参数:

>>> x = staticmethod(3)

而且它确实不可调用:

>>> x()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'staticmethod' object is not callable

staticmethod 只是存储对其参数的引用。当您尝试访问 staticmethod 对象作为 class 对象的属性或 class 的实例时,会发生 "magic"。当你这样做时,你会得到 staticmethod 方法的 __get__ 方法的结果,这是......你最初包装的东西。

>>> x.__get__(x)
3

不要担心我们为什么要传递 x 作为参数;可以这么说,staticmethod.__get__ 大多忽略了它的论点。

当您将函数包装在 class 语句中时,staticmethod 会保存对该函数的引用,以便稍后在您请求时调用。

>>> class Foo(object):
...   @staticmethod
...   def x():
...     pass
...
>>> type(Foo.__dict__['x'])
<type 'staticmethod'>
>>> type(Foo.x)
<type 'function'>

实例方法之所以如此工作,是因为 function.__get__ return 是 method 的一个实例,从某种意义上说,这只是原始函数部分应用了调用它的实例。您可能已经看到 x.foo()type(x).foo(x) 相同。 原因是真的,因为x.foo首先解析为type(x).foo,它本身计算为type(x).__dict__['foo'].__get__(x, type(x)function.__get__ 的 return 值基本上是函数 foo 的包装器,但 x 已经作为第一个参数提供。

staticmethod的主要目的是提供一种不同的__get__方法。

顺便说一下,classmethod 有相同的目的。 classmethod.__get__ returns 以 class 作为第一个参数调用包装函数的东西,无论您从中调用 class 方法class 或 class 本身的实例。

How can it wrap any other object than a function object?

很容易。

class Example(object):
    example = staticmethod(5)

print(Example.example) # prints 5

您可以将任何内容传递给 staticmethod 构造函数。

Even if this doesn't fail, how does it make any sense?

通常不检查,但staticmethod不检查。

How is it usually a wrapper around a user-defined method object instead of a function object?

不是。那部分是错误的。

How is it that static method objects are not themselves callable? How do calls to these work, then?

descriptor protocol。静态方法对象有一个 __get__ 方法 returns 它们包装的任何对象。属性访问调用此 __get__ 方法和 returns what __get__ returns.