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

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 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. [...]

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.