返回介绍

__init__.py 包文件

发布于 2024-01-29 22:24:16 字数 1829 浏览 0 评论 0 收藏 0

如果选择使用包导入,就必须多遵循一条约束:包导入语句的路径中的每个目录内都必须有__init__.py这个文件,否则导入包会失败。也就是说,在我们所采用的例子中,dir1和dir2内都必须包含__init__.py这个文件。容器目录dir0不需要这类文件,因为其本身没列在import语句之中。更正式说法是,像这样的目录结构:

以及这种形式的import语句:

必须遵循下列规则:

·dir1和dir2中必须都含有一个__init__.py文件。

·dir0是容器,不需要__init__.py文件;如果有的话,这个文件也会被忽略。

·dir0(而非dir0\dir1)必须列在模块搜索路径上(也就是此目录必须是主目录,或者列在PYTHONPATH之中)。

结果就是,这个例子的目录结构应该是这样(以缩进表示目录嵌套结果)。

__init__.py可以包含Python程序代码,就像普通模块文件。这类文件从某种程度上讲就像是Python的一种声明,尽管如此,也可以完全是空的。作为声明,这些文件可以防止有相同名称的目录不小心隐藏在模块搜索路径中,而之后才出现真正所需要的模块。没有这层保护,Python可能会挑选出和程序代码无关的目录,只是因为有一个同名的目录刚好出现在搜索路径上位置较前的目录内。

更通常的情况下,__init__.py文件扮演了包初始化的钩子、替目录产生模块命名空间以及使用目录导入时实现from*(也就是from...import*)行为的角色。

包的初始化

Python首次导入某个目录时,会自动执行该目录下__init__.py文件中的所有程序代码。因此,这类文件自然就是放置包内文件所需要初始化的代码的场所。例如,包可以使用其初始化文件,来创建所需要的数据文件、连接数据库等。一般而言,如果直接执行,__init__.py文件没什么用,当包首次读取时,就会自动运行。

模块命名空间的初始化

在包导入的模型中,脚本内的目录路径,在导入后会变成真实的嵌套对象路径。例如,上一个例子中,导入后,表达式dir1.dir2会运行,并返回一个模块对象,而此对象的命名空间包含了dir2的__init__.py文件所赋值的所有变量名。这类文件为目录(没有实际相配的模块文件)所创建的模块对象提供了命名空间。

from*语句的行为

作为一个高级功能,你可以在__init__.py文件内使用__all__列表来定义目录以from*语句形式导入时,需要导出什么。在__init__.py文件中,__all__列表是指当包(目录)名称使用from*的时候,应该导入的子模块的名称清单。如果没有设定__all__,from*语句不会自动加载嵌套于该目录内的子模块。取而代之的是,只加载该目录的__init__.py文件中赋值语句定义的变量名,包括该文件中程序代码明确导入的任何子模块。例如,某目录中__init__.py内的语句from submodule import X,会让变量名X可在该目录的命名空间内使用(我们将在第24章看到__all__的另一种用法)。

如果你用不着这类文件,也可以让这类文件保持空白。不过,为了让目录导入完全运作,这类文件就得存在。

注意:不要把包__init__.py文件和我们将在本书下一部分中介绍的类__init__构造函数方法搞混淆了。前者是当导入初次遍历一个包目录的时候所运行的代码的文件,而后者是当创建实例的时候才调用。它们都具有初始化的作用,但是,它们有很大的不同。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文