This works and happily prints 81:
class X:
mypow = pow
print(X().mypow(3, 4))
But why? Isn't the method given the extra "self" argument and should be utterly confused?
For comparison, I also tried it with my own Pow
function:
def Pow(x, y, z=None):
return x ** y
class Y:
myPow = Pow
print(Pow(3, 4))
print(Y().myPow(3, 4))
The direct function call prints 81 and the method call crashes as expected, as it does get that extra instance argument:
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 does Pythons own pow
work here? The documentation didn't help and I couldn't find the source.
This is because python functions defined in C (builtins) have auto handled self argument. Here is pow function header :
static PyObject *
math_pow(PyObject *self, PyObject *args)
Here you can see that self is always passed by interpreter.
This behavior is connected to method binding. Have a look at what Python tells you about these functions/methods:
>> pow
<built-in function pow>
>>> X.mypow
<built-in function pow>
>>> X().mypow
<built-in function pow>
and
>>> Pow
<function Pow at 0x7f88f5715f50>
>>> Y.myPow
<unbound method Y.Pow>
>>> Y().myPow
<bound method Y.Pow of <__main__.Y instance at 0x7f88f57117e8>>
Further the documentation states:
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. [...]
But built-in functions don't have a __get__()
method. That's why pow
wasn't bound and could be used the way you observed, while Pow
couldn't.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With