为什么 `class X: mypow = pow` 有效? “自我”呢?

Why does `class X: mypow = pow` work? What about `self`?

这有效并愉快地打印 81:

class X:
    mypow = pow

print(X().mypow(3, 4))

但是为什么呢?方法不是给出了额外的 "self" 参数并且应该完全混淆吗?

为了对比,我也用自己的Pow函数试了一下:

def Pow(x, y, z=None):
    return x ** y

class Y:
    myPow = Pow

print(Pow(3, 4))
print(Y().myPow(3, 4))

直接函数调用打印 81 并且方法调用按预期崩溃,因为它确实获得了额外的实例参数:

Python 3:  TypeError: unsupported operand type(s) for ** or pow(): 'Y' and 'int'
Python 2:  TypeError: unsupported operand type(s) for ** or pow(): 'instance' and 'int'

Why/how Pythons 拥有 pow 在这里工作吗? The documentation 没有帮助,我找不到来源。

这是因为 python 在 C 中定义的函数(内置函数)具有自动处理的 self 参数。这是 pow 函数头:

static PyObject * math_pow(PyObject *self, PyObject *args) 在这里你可以看到 self 总是由解释器传递。

此行为与 method binding 相关。看看 Python 告诉你这些 functions/methods:

>> pow
<built-in function pow>
>>> X.mypow
<built-in function pow>
>>> X().mypow
<built-in function pow>

>>> Pow
<function Pow at 0x7f88f5715f50>
>>> Y.myPow
<unbound method Y.Pow>
>>> Y().myPow
<bound method Y.Pow of <__main__.Y instance at 0x7f88f57117e8>>

进一步的文档说明:

Class dictionaries store methods as functions. In a class definition, methods are written using def and lambda, the usual tools for creating functions. [...]

To support method calls, functions include the __get__() method for binding methods during attribute access. This means that all functions are non-data descriptors which return bound or unbound methods depending whether they are invoked from an object or a class. [...]

但是内置函数没有 __get__() 方法。这就是为什么 pow 没有绑定并且可以按照您观察到的方式使用,而 Pow 不能。

嗯,@tynn已经指出了pow没有__get__的原因,所以不能转化为bound method

但是为什么呢?所有这些事情背后的关键是descriptor protocol。如果有人想更好地理解Python,那么应该去理解descriptor protocol,这并不难,但非常简单和强大。