Все, что делает from __future__ import print_function
, это переключает флаг в анализаторе, чтобы он прекратил рассматривать print
как ключевое слово; Как только это будет сделано, ссылки на print
станут подобными ссылкам на любое другое не ключевое слово, которое составляет допустимое имя переменной (они проходят поиск в LEGB и обнаруживаются в B LEGB, встроенной области видимости). Это поведение жестко запрограммировано глубоко в интерпретаторе Python; нет никакого способа добиться подобного эффекта для любого другого ключевого слова без создания пользовательской версии Python или участия в какой-либо другой вопиющей хакерской деятельности, выходящей далеко за рамки разумной проблемы.
Начиная с версии 2.6, __builtin__
имеет функцию print
, поэтому любой модуль, который использует from __future__ import print_function
(и поэтому может ссылаться на имя print
в отличие от Ключевое слово print
) будет видеть __builtin__.print
(если оно не было скрыто чем-либо в локальной, вложенной или глобальной области видимости). Он по-прежнему там для каждого модуля, но в модулях без импорта __future__
ссылки на print
преобразуются в ключевое слово во время компиляции и заменяются необработанным байт-кодом, реализующим специальный print
оператор (так же, как del
и return
ведут себя; вы не можете назвать ни одну из этих переменных по одной и той же причине, они являются ключевыми словами), поэтому модули без импорт никогда не получит возможность поиска функции print
.
Это не распространяется на другие случаи, потому что __future__
не имеет других случаев, когда одна из его функций преобразует ключевое слово в не ключевое слово. Для всех других реальных встроенных функций возможность перезаписать их для каждого модуля так же просто, как присвоить имя в глобальной области видимости (затенение для этого модуля), например ::
def abs(x):
return x # Who needs absolute value anyway?
# From here on out, references to abs in this module see your override, not the built-in
Хотя встроенное встроенное устройство можно переназначить глобально, это ужасная идея (поскольку каждый другой модуль, использующий его, скорее всего, использует исходное поведение встроенных модулей). Тем не менее, это не сложно:
import __builtin__
def abs(x):
return x # Who needs absolute value anyway?
__builtin__.abs = abs
# *Every* module now sees your terrible monkeypatch, on your own head be it