为什么 `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
,这并不难,但非常简单和强大。
这有效并愉快地打印 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
andlambda
, 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
,这并不难,但非常简单和强大。