首页 > Python基础教程 >
-
模块(2)
相反,使用类似 import item.subitem.subsubitem
这样的语法时,这些子项必须是包,最后的子项可以是包或模块,但不能是前面子项中定义的类、函数或变量。
6.4.1. 从 * 导入包
那么当用户写下 from sound.effects import *
时会发生什么事?理想中,总是希望在文件系统中找出包中所有的子模块,然后导入它们。这可能会花掉很长时间,并且出现期待之外的边界效应,导出了希望只能显式导入的包。
对于包的作者来说唯一的解决方案就是给提供一个明确的包索引。import 语句按如下条件进行转换:执行 from package import *
时,如果包中的 __init__.py
代码定义了一个名为 __all__
的列表,就会按照列表中给出的模块名进行导入。新版本的包发布时作者可以任意更新这个列表。如果包作者不想 import * 的时候导入他们的包中所有模块,那么也可能会决定不支持它( 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
没有错误!事实上,除非导入的模块需要使用其它包中的同名子模块,否则这是推荐的写法。
6.4.2. 包内引用
如果包中使用了子包结构(就像示例中的 sound
包),可以按绝对位置从相邻的包中引入子模块。例如,如果 sound.filters.vocoder
包需要使用 sound.effects
包中的 echo
模块,它可以 from sound.Effects import echo
。
你可以用这样的形式 from module import name
来写显式的相对位置导入。那些显式相对导入用点号标明关联导入当前和上级包。以 surround
模块为例,你可以这样用:
from . import echo
from .. import formats
from ..filters import equalizer
需要注意的是显式或隐式相对位置导入都基于当前模块的命名。因为主模块的名字总是 "__main__"
,Python 应用程序的主模块应该总是用绝对导入。
6.4.3. 多重目录中的包
包支持一个更为特殊的特性, __path__。 在包的 __init__.py
文件代码执行之前,该变量初始化一个目录名列表。该变量可以修改,它作用于包中的子包和模块的搜索功能。
这个功能可以用于扩展包中的模块集,不过它不常用。
Footnotes
[1] | 事实上函数定义既是“声明”又是“可执行体”;执行体由函数在模块全局语义表中的命名导入。 |