Насправді, поведінка в __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__()
вже робить функція, та обходячи імена, але це означало б дублювання деяких зусиль. Таким чином, замість того , реалізація MADE __import__()
повернути праву більшість модуля замість самого лівих один , якщо і тільки якщо fromlist передається і не спустошити.
( Синтаксис import pkg as p
and та from pkg import mod as m
нічого не змінює в цій історії, крім того, яким місцевим іменам присвоюється - __import__()
функція не бачить нічого іншого, коли as
використовується, все залишається у реалізації import
оператора.)