Фактически поведение __import__()
происходит полностью из-за реализации инструкции import
, которая вызывает __import__()
. Там в основном пять несколько различных способов __import__()
могут быть вызваны import
(с двумя основными категориями):
import pkg
import pkg.mod
from pkg import mod, mod2
from pkg.mod import func, func2
from pkg.mod import submod
В первом и второй случай, то import
оператор должен назначить «самую левую» объект модуля для «самое левое» имя: pkg
. После import pkg.mod
вы можете сделать pkg.mod.func()
, потому что оператор import
вводит локальное имя pkg
, которое является объектом модуля, который имеет атрибут mod
. Таким образом, функция __import__()
должна вернуть объект модуля «самый левый», чтобы он мог быть назначен pkg
. Эти два утверждения импорта, таким образом перевести:
pkg = __import__('pkg')
pkg = __import__('pkg.mod')
В третьем, четвертом и пятом случае import
оператор должен делать больше работы: он должен назначить (потенциально) несколько имен, которые он должен получить от объект модуля. Функция __import__()
может возвращать только один объект, и нет никакой реальной причины, чтобы он извлекал каждое из этих имен из объекта модуля (и это сделало бы реализацию намного сложнее.) Таким образом, простой подход был бы чем-то вроде (для третий случай):
tmp = __import__('pkg')
mod = tmp.mod
mod2 = tmp.mod2
Однако, это не будет работать, если pkg
является пакет и mod
или mod2
модули в этом пакете , которые уже не импортированной, так как они находятся в третьем и пятом случае. Функция __import__()
должна знать, что mod
и mod2
- это имена, которые оператор import
захочет иметь доступный, чтобы он мог видеть, являются ли они модулями и пытаются их импортировать.Поэтому вызов ближе к:
tmp = __import__('pkg', fromlist=['mod', 'mod2'])
mod = tmp.mod
mod2 = tmp.mod2
, который вызывает __import__()
попробовать и нагрузки pkg.mod
и pkg.mod2
, а также pkg
(но если mod
или mod2
не существует, это не ошибка в __import__()
вызова, продуцирующих ошибка остается в import
заявление) Но это еще не правильная вещь для четвертого и пятого примера, потому что, если вызов так:.
tmp = __import__('pkg.mod', fromlist=['submod'])
submod = tmp.submod
затем tmp
бы в конечном итоге pkg
, как и раньше, а не модуль pkg.mod
, из которого вы хотите получить атрибут submod
. Реализация могла бы решить сделать так, чтобы оператор import
выполнял дополнительную работу, разделяя имя пакета на .
, как функция __import__()
, уже выполняет и перемещает имена, но это означало бы дублирование некоторых усилий. Таким образом, вместо выполненной реализации __import__()
верните самый правый модуль вместо самый левый один тогда и только тогда, когда из списка передан и не пуст.
(Синтаксис import pkg as p
и from pkg import mod as m
ничего об этой истории, кроме которой местные имен получить назначены не менять - функции __import__()
не видит ничего другого, когда as
используется, все это остается в реализации в import
заявления.)
Говоря «вот как работает реализация», не отвечает на мой вопрос. Почему это работает? Высказывание формы «для эмуляции имени импорта ...» ближе, но при каких обстоятельствах вам это нужно? Исход из списка не имеет отличия от того, как работает __import__, поэтому я не вижу, где есть случай, когда вам нужно передать его, чтобы подражать чему-либо, кроме того, что должно быть очевидным поведением функции. – ieure
Вы правы, это попрошайничает вопрос. Я обновил свой ответ, чтобы дать более релевантный ответ. – mipadi