事实上,__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。导入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 __()调用中的错误;生成错误留给导入语句。)但是对于第四和第五个例子来说仍然是不正确的,因为如果调用是这样:

tmp = __import__('pkg.mod', fromlist=['submod'])
submod = tmp.submod

那么tmp将最终变为pkg,如前所述,而不是要获取submod属性的pkg.mod模块。实现可能已经决定让import语句做额外的工作,拆分包名。像__import __()函数已经和遍历名称,但这将意味着重复一些努力。所以,相反,实现使__import __()返回最右边的模块,而不是最左边的一个,当且仅当fromlist传递而不是空。

(导入pkg作为p和从pkg import mod作为m语法不会改变任何关于这个故事,除了哪些本地名称被分配到 – __import __()函数看到没有什么不同,使用时,它都保留在导入语句实现。)