In der Tat ist das Verhalten von __import__()ausschließlich auf die Implementierung der importAnweisung zurückzuführen, die aufruft __import__(). Es gibt im Grunde fünf leicht unterschiedliche Weise __import__()können aufgerufen werden import(mit zwei Hauptkategorien):
import pkg
import pkg.mod
from pkg import mod, mod2
from pkg.mod import func, func2
from pkg.mod import submod
Im ersten und zweiten Fall sollte die importAnweisung das Modulobjekt "ganz links" dem Namen "ganz links" zuweisen : pkg. Nachdem import pkg.modSie dies tun können, pkg.mod.func()weil die importAnweisung den lokalen Namen eingeführt hat pkg, der ein Modulobjekt ist, das ein modAttribut hat. Die __import__()Funktion muss also das Modulobjekt "ganz links" zurückgeben, damit es zugewiesen werden kann pkg. Diese beiden Importanweisungen bedeuten also:
pkg = __import__('pkg')
pkg = __import__('pkg.mod')
Im dritten, vierten und fünften Fall muss die importAnweisung mehr Arbeit leisten: Sie muss (möglicherweise) mehreren Namen zuweisen, die sie vom Modulobjekt erhalten muss. Die __import__()Funktion kann nur ein Objekt zurückgeben, und es gibt keinen wirklichen Grund, jeden dieser Namen aus dem Modulobjekt abzurufen (und dies würde die Implementierung viel komplizierter machen). Der einfache Ansatz wäre also ungefähr so (für den dritten) Fall):
tmp = __import__('pkg')
mod = tmp.mod
mod2 = tmp.mod2
Dies funktioniert jedoch nicht, wenn pkges sich um ein Paket handelt und / mododer mod2um Module in diesem Paket , die nicht bereits importiert wurden , wie dies im dritten und fünften Fall der Fall ist. Die __import__()Funktion muss das wissen modund mod2sind Namen, auf die die importAnweisung zugreifen soll, damit sie sehen kann, ob es sich um Module handelt, und versucht, sie auch zu importieren. Der Anruf ist also näher an:
tmp = __import__('pkg', fromlist=['mod', 'mod2'])
mod = tmp.mod
mod2 = tmp.mod2
was bewirkt , dass __import__()und Last , um zu versuchen pkg.modund pkg.mod2sowie pkg(aber wenn mododer mod2nicht existieren, es ist nicht ein Fehler in dem __import__()Aufruf, einen Fehler erzeugen, das den blieb import. statement) Aber das ist noch nicht das Richtige für die vierten und fünftes Beispiel, denn wenn der Anruf so wäre:
tmp = __import__('pkg.mod', fromlist=['submod'])
submod = tmp.submod
Dann tmpwäre es pkgwie zuvor und nicht das pkg.modModul, von dem Sie das submodAttribut erhalten möchten . Die Implementierung hätte sich dafür entscheiden können, damit die importAnweisung zusätzliche Arbeit leistet, den Paketnamen aufteilt, .wie es die __import__()Funktion bereits tut, und die Namen durchläuft, aber dies hätte bedeutet, einen Teil des Aufwands zu duplizieren. Anstatt also, macht die Umsetzung __import__()Rückkehr die am weitesten rechts stehenden Modul anstelle des am weitesten links ein , wenn und nur wenn fromlist geben wird und nicht leeren.
(Die Syntax import pkg as pund from pkg import mod as mändert nichts an dieser Geschichte, außer den lokalen Namen, denen zugewiesen wird. Die __import__()Funktion sieht bei Verwendung nichts anderes asaus, alles bleibt in der importAnweisungsimplementierung.)