Python class方法:实例成员和class成员有什么区别?

Python classmethods: what's the difference between a member of an instance and a member of the class?

在python中,staticmethod是"just functions",我可以用两种不同的方式来引用它们:

>>> class A:
...     @staticmethod
...     def f():
...         pass
... 
>>> a=A()
>>> A.f
<function A.f at 0x7f20f8cd3f28>
>>> a.f
<function A.f at 0x7f20f8cd3f28>
>>> a.f is A.f
True

a.fA.f都是指向同一个对象的名称,恰好是"just a function"。太好了。

现在,假设我有一个 classmethod:

>>> class B:
...     @classmethod
...     def f(cls):
...         pass
... 
>>> b=B()
>>> b.f is B.f
False

我知道 b.fB.f 不是 函数:它们是 绑定方法 。这意味着 cls 参数是隐式的,并且总是等于 B。因此,我会理解如果 B2B 的子类,B2().f is B().f 将是错误的,因为它们是具有不同 cls 参数的绑定方法。但我不明白为什么 B().f is B.f 会产生 False。它们不应该是同一个对象吗,就像 A().fA.f 一样?

编辑:这个问题与“What is the difference between @staticmethod and @classmethod in Python?”不同。我知道 staticmethodclassmethod 之间的区别。我想知道一件具体的事情,"umbrella" 问题链接中没有提到。

B().fB.f 是不同的对象,因为每次您通过属性访问引用非静态方法时,Python 都会创建一个新的绑定方法对象。

例如,B.f is B.f 也是 False

>>> B.f is B.f
False

同样,即使实例保持不变,您也会得到一个新的方法对象:

>>> b = B()
>>> b.f is b.f
False

@staticmethod 创建一个新的静态方法对象,但是

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.

(来自 Data model

在这种情况下 A.f 总是 returns 相同的 f 函数对象。