你可以把包看成是文件系统中的目录,并把模块看成是目录中的文件,但请不要对这个类似做过于字面的理解,因为包和模块不是必须来自于文件系统。 为了方便理解本文档,我们将继续使用这种目录和文件的类比。 与文件系统一样,包通过层次结构进行组织,在包之内除了一般的模块,还可以有子包。
要注意的一个重点概念是所有包都是模块,但并非所有模块都是包。 或者换句话说,包只是一种特殊的模块。 特别地,任何具有 属性的模块都会被当作是包。
Python 定义了两种类型的包, 和 命名空间包。 常规包是传统的包类型,它们在 Python 3.2 及之前就已存在。 常规包通常以一个包含 init.py
文件的目录形式实现。 当一个常规包被导入时,这个 init.py
文件会隐式地被执行,它所定义的对象会被绑定到该包命名空间中的名称。 文件可以包含与任何其他模块中所包含的 Python 代码相似的代码,Python 将在模块被导入时为其添加额外的属性。
例如,以下文件系统布局定义了一个最高层级的 parent
包和三个子包:
5.2.2. 命名空间包
命名空间包是由多个 部分 构成的,每个部分为父包增加一个子包。 各个部分可能处于文件系统的不同位置。 部分也可能处于 zip 文件中、网络上,或者 Python 在导入期间可以搜索的其他地方。 命名空间包并不一定会直接对应到文件系统中的对象;它们有可能是无实体表示的虚拟模块。
命名空间包的 path
属性不使用普通的列表。 而是使用定制的可迭代类型,如果其父包的路径 (或者最高层级包的 ) 发生改变,这种对象会在该包内的下一次导入尝试时自动执行新的对包部分的搜索。
另请参阅 PEP 420 了解对命名空间包的规格描述。