Python имеет модуль builtins
, в котором хранятся «действительно глобальные» вещи - обычно просто стандартные встроенные функции и типы .В Python 2 он назывался __builtin__
, но работал в основном так же.
Этот модуль можно импортировать, как и любой другой модуль, но он также волшебным образом предоставляет встроенные имена для каждого другого модуля (который не 'скрыть их).
Если вам интересно, как это работает, документы builtins
говорят:
В качестве детали реализации большинство модулей имеют имя __builtins__
сделан доступным как часть их глобалов.Значение __builtins__
обычно является либо этим модулем, либо значением атрибута __dict__
этого модуля.Поскольку это деталь реализации, она не может использоваться альтернативными реализациями Python.
И exec
говорит:
ЕслиСловарь globals не содержит значения для ключа __builtins__
, ссылка на словарь встроенного модуля builtins
вставлена под этим ключом.Таким образом, вы можете контролировать, какие встроенные функции доступны для исполняемого кода, вставляя свой собственный словарь __builtins__
в глобальные переменные перед передачей его в exec()
.
Итак, по крайней мере в CPython, когда вы оцениваетеabs
, он ищется в globals()['abs']
, там не найден, а затем ищется в globals()['__builtins__'].__dict__['abs']
.
И всякий раз, когда Python (или, по крайней мере, CPython) создает новый объект модуля, его код выполняетсяпротив globals
с empty
__builtins__
, что означает, что значение модуля по умолчанию builtins
заполняется, и это работает.И этот globals
копируется для самой функции и класса, определенных в модуле (и всего, что вы делаете явно с globals
без явной замены __builtins__
), так что он работает и внутри функций и классов.