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__'
In addition to built-in functions, a large number of pre-defined functions are also available as a part of libraries bundled with Python distributions. These functions are defined in modules are called built-in modules. Built-in modules are written in C and integrated with the Python shell.
These functions are defined in modules are called built-in modules. Built-in modules are written in C and integrated with the Python shell. Each built-in module contains resources for certain system-specific functionalities such as OS management, disk IO, etc.
Built-in functions are similar to operation codes in that they perform operations on data you specify. Built-in functions can be used in expressions. Additionally, constant-valued built-in functions can be used in named constants. These named constants can be used in any specification.
In general, the arguments of the built-in function are similar to the factor 1 and factor 2 fields of an operation code. Another useful feature of built-in functions is that they can simplify maintenance of your code when used on the definition specification. The following example demonstrates this feature.
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.
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