Methods have an attribute, __self__
, that holds the instance to be passed when the underlying function gets invoked. Apparently, so do built-in functions.
In Python 3, they hold the module object:
>>> len.__self__
<module 'builtins' (built-in)>
>>> sys.getrefcount.__self__ # also for other builtin modules
<module 'sys' (built-in)>
In Python 2, on the other hand, they hold None
:
>>> type(len.__self__)
<type 'NoneType'>
>>> sys.getrefcount.__self__
<type 'NoneType'>
Does anyone know why there's a discrepancy here? In addition to that, why do these even have a __self__
and aren't like Python level module functions that lack a __self__
attribute:
>>> from pprint import pprint
>>> pprint.__self__
AttributeError: 'function' object has no attribute '__self__'
I believe I've found the reason for the discrepancy thanks to issue14003. It seems it is due to a change in the module creation API from Python 2 to 3.
In Python 2, during the construction of modules with Py_InitModule4
, a PyObject *self
argument was available that could have the value of None
if writters of extention modules wished, as documented:
If
self
is non-NULL
, it will be passed to the functions of the module as their (otherwiseNULL
) first parameter
Most of the built-in standard library modules apparently chose that path and as such the result of builtin_function.__self__
is None
:
mod = Py_InitModule4("__builtin__", builtin_methods,
builtin_doc, (PyObject *)NULL,
PYTHON_API_VERSION);
In Python 3, the API for creating modules changed and that option disappeared. The function for creating modules, PyModule_Create2
, doesn't take a self
argument that's allowed to be None
. Instead, it calls PyModule_AddFunctions
(which calls the internal _add_methods_to_object
to add the functions to the module) and unconditionally sets the __self__
attribute on the builtin functions to be the module.
So that's why for len
the builtins
module is returned. AFAIK, it isn't used anywhere inside the function body so it's purpose isn't special in any way.
Props to @user2357112 for making me feel silly, builtin_method
and builtin_function
are actually the same struct so it makes sense for builtin functions to share the __self__
attribute found in methods.
The function
type, on the other hand, really has no point in having it since it isn't shared in any way with the method
type.