Ответ 1
Вы можете видеть, какой модуль определен функцией через атрибут __module__
. Из документации модели данных Python на __module__
:
Название модуля, в котором была определена функция, или Нет, если недоступно.
Пример:
>>> from re import compile
>>> compile.__module__
're'
>>> def foo():
... pass
...
>>> foo.__module__
'__main__'
>>>
В модели данных позже упоминается, что классы имеют одинаковый атрибут:
__module__
- это имя модуля, в котором был определен класс.
>>> from datetime import datetime
>>> datetime.__module__
'datetime'
>>> class Foo:
... pass
...
>>> Foo.__module__
'__main__'
>>>
Вы также можете сделать это со встроенными именами, такими как int
и list
. Вы можете получить доступ к ним из модуля builtins
.
>>> int.__module__
'builtins'
>>> list.__module__
'builtins'
>>>
Я могу использовать
int
иlist
безfrom builtins import int, list
. Итак, какint
иlist
становятся доступными в моей программе?
Это потому, что int
и list
являются встроенными именами. Вам не нужно явно импортировать их для Python, чтобы иметь возможность находить их в текущем пространстве имен. Вы можете убедиться в этом в исходный код виртуальной машины CPython. Как упоминалось в @user2357112, встроенные имена доступны, когда глобальный поиск завершается с ошибкой. Вот соответствующий фрагмент:
if (v == NULL) {
v = PyDict_GetItem(f->f_globals, name);
Py_XINCREF(v);
if (v == NULL) {
if (PyDict_CheckExact(f->f_builtins)) {
v = PyDict_GetItem(f->f_builtins, name);
if (v == NULL) {
format_exc_check_arg(
PyExc_NameError,
NAME_ERROR_MSG, name);
goto error;
}
Py_INCREF(v);
}
else {
v = PyObject_GetItem(f->f_builtins, name);
if (v == NULL) {
if (PyErr_ExceptionMatches(PyExc_KeyError))
format_exc_check_arg(
PyExc_NameError,
NAME_ERROR_MSG, name);
goto error;
}
}
}
}
В приведенном выше коде CPython сначала ищет имя в глобальной области. Если это не удается, оно возвращается и пытается получить имя от сопоставления встроенных имен в текущем объекте фрейма. Это то, что f->f_builtins
.
Вы можете наблюдать это сопоставление с уровня Python, используя sys._getframe()
:
>>> import sys
>>> frame = sys._getframe()
>>>
>>> frame.f_builtins['int']
<class 'int'>
>>> frame.f_builtins['list']
<class 'list'>
>>>
sys._getframe()
возвращает фрейм в верхней части стека вызовов. В этом случае это рамка для области модуля. Как вы можете видеть выше, отображение f_builtins
для фрейма содержит классы int
и list
, поэтому Python автоматически предоставил эти имена. Другими словами, он "встроил" их в сферу охвата; следовательно, термин "встроенные".