Подтвердить что ты не робот

Почему __self__ встроенных функций возвращает встроенный модуль, к которому он принадлежит?

У методов есть атрибут __self__, который содержит экземпляр, который должен быть передан при вызове базовой функции. По-видимому, так делают встроенные функции.

В Python 3 они хранят объект модуля:

>>> len.__self__
<module 'builtins' (built-in)>
>>> sys.getrefcount.__self__  # also for other builtin modules
<module 'sys' (built-in)>

В Python 2, с другой стороны, они содержат None:

>>> type(len.__self__)
<type 'NoneType'>
>>> sys.getrefcount.__self__
<type 'NoneType'>

Кто-нибудь знает, почему здесь существует несоответствие? В дополнение к этому, почему у них даже есть __self__ и они не похожи на функции модуля уровня Python, которые не имеют атрибута __self__:

>>> from pprint import pprint
>>> pprint.__self__
AttributeError: 'function' object has no attribute '__self__'
4b9b3361

Ответ 1

Я считаю, что я нашел причину несоответствия благодаря issue14003. Похоже, что это связано с изменением API-интерфейса создания модуля от Python 2 до 3.

В Python 2 при построении модулей с Py_InitModule4 был доступен аргумент PyObject *self, который мог бы иметь значение None, если пожелаете, чтобы сгенерировали модули расширения, как описано:

Если self не NULL, он будет передан функциям модуля в качестве их (иначе NULL) первого параметра

Большинство встроенных стандартных библиотечных модулей по-видимому, выбрали этот путь, и поэтому результат builtin_function.__self__ равен None:

mod = Py_InitModule4("__builtin__", builtin_methods,
                     builtin_doc, (PyObject *)NULL,
                     PYTHON_API_VERSION);

В Python 3 API для создания модулей изменился и эта опция исчезла. Функция для создания модулей PyModule_Create2 не принимает аргумент self, который может быть None. Вместо этого он вызывает PyModule_AddFunctions (который вызывает внутренний _add_methods_to_object, чтобы добавить функции в модуль) и безоговорочно устанавливает атрибут __self__ для встроенных функций как модуль.

Итак, почему для len возвращается модуль builtins. AFAIK, он нигде не используется внутри тела функции, поэтому цель не является особенной.


Опоры @user2357112 заставляют меня чувствовать себя глупо, builtin_method и builtin_function на самом деле одна и та же структура, поэтому имеет смысл встроенные функции для совместного использования атрибута __self__, найденного в методах.

Тип function, с другой стороны, действительно не имеет смысла иметь его, поскольку он не используется каким-либо образом с типом method.