6.4.1. 从包中导入 *
当用户写 from sound.effects import *
会发生什么?理想情况下,人们希望这会以某种方式传递给文件系统,找到包中存在哪些子模块,并将它们全部导入。这可能需要很长时间,导入子模块可能会产生不必要的副作用,这种副作用只有在显式导入子模块时才会发生。
唯一的解决方案是让包作者提供一个包的显式索引。import
语句使用下面的规范:如果一个包的 __init__.py
代码定义了一个名为 __all__
的列表,它会被视为在遇到 from package import *
时应该导入的模块名列表。在发布该包的新版本时,包作者可以决定是否让此列表保持更新。包作者如果认为从他们的包中导入 * 的操作没有必要被使用,也可以决定不支持此列表。例如,文件 sound/effects/__init__.py
可以包含以下代码:
__all__ = ["echo", "surround", "reverse"]
这意味着 from sound.effects import *
将导入 sound
包的三个命名子模块。
如果没有定义 __all__
,from sound.effects import *
语句 不会 从包 sound.effects
中导入所有子模块到当前命名空间;它只确保导入了包 sound.effects
(可能运行任何在 __init__.py
中的初始化代码),然后导入包中定义的任何名称。 这包括 __init__.py
定义的任何名称(以及显式加载的子模块)。它还包括由之前的 import
语句显式加载的包的任何子模块。思考下面的代码:
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
在这个例子中, echo
和 surround
模块是在执行 from...import
语句时导入到当前命名空间中的,因为它们定义在 sound.effects
包中。(这在定义了 __all__
时也有效。)
虽然某些模块被设计为在使用 import *
时只导出遵循某些模式的名称,但在生产代码中它仍然被认为是不好的做法。
请记住,使用 from package import specific_submodule
没有任何问题! 实际上,除非导入的模块需要使用来自不同包的同名子模块,否则这是推荐的表示法。