浅谈Python中的包
Package的定义(你以为的)
-
你在很多的地方都能看到关于package的定义:在Python中在当前目录下有__init__.py文件的目录即为一个package。
-
嗯,包括python目前的官网文档也是类似这么介绍的
https://docs.python.org/zh-cn/3.9/tutorial/modules.html#packages Python 只把含 __init__.py 文件的目录当成包
https://docs.python.org/3.9/tutorial/modules.html#packages The __init__.py files are required to make Python treat directories containing the file as packages
3.9如此,3.11也是的,可能是文档维护人员的工资没发?
Package的定义(应该是这样的)
- 然在上面的文档中,有这样一句
- 包是一种用“点式模块名”构造 Python 模块命名空间的方法
- Packages are a way of structuring Python’s module namespace by using “dotted module names”.
我认为是比较符合当前的设定的
是否需要初始化文件
- 看上面这个文章,尾部有这样的一段说明
Much of the Python documentation states that an __init__.py file must be present in the package directory when creating a package. This was once true. It used to be that the very presence of __init__.py signified to Python that a package was being defined. The file could contain initialization code or even be empty, but it had to be present.
Starting with Python 3.3, Implicit Namespace Packages were introduced. These allow for the creation of a package without any __init__.py file. Of course, it can still be present if package initialization is needed. But it is no longer required.
- 简陋的翻译一下
很多的python文档说__init__.py必须要存在于package目录中,当你创建一个package的时候(注:事实上IDE如pycharm也是这么做的,默认就给你创建了..)。这曾经是对的。曾经它出现在一个python的目录中就表示了你在创建一个包。这个__init__.py文件可以包含初始化文件或者为空,但它必须存在。
从Python3.3开始,开始引入了隐式命名空间包的概念。这就允许了创建包的时候不需要__init__.py。当然如果一个包要初始化,它仍然是需要的。但是,不再是必要的!
PEP 420 Implicit Namespace Packages
-
在Specification章节
Regular packages will continue to have an __init__.py and will reside in a single directory. Namespace packages cannot contain an __init__.py
-
它也提到了namespace packages和regular packages的区别
- Portions of namespace packages need not all come from the same directory structure, or even from the same loader. Regular packages are self-contained: all parts live in the same directory hierarchy.
- Namespace packages have no
__file__
attribute. - Namespace packages’
__path__
attribute is a read-only iterable of strings, which is automatically updated when the parent path is modified. - Namespace packages have no
__init__.py
module. - Namespace packages have a different type of object for their
__loader__
attribute
这个区别实在不好测试,比想象的要繁琐很多
一个简单的测试
-
目录结构
D:\pythonProject\AutoTest\PackageTest (7.08KB) ├── NamespacePack (2b) │ ├── demoNP.py (24b) ├── RegularPack (35b) │ ├── demoRP.py (24b) │ ├── __init__.py (2b) └── testPack.py (114b)
-
区别就是在pycharm上创建一个目录NamespacePack,创建一个package(RegularPack)
-
demoNP.py
nameNP = 'NamespacePack'
-
demoRP.py
nameRP = 'RegularPack'
-
__init__.py为空
-
testPack.py
from NamespacePack.demoNP import nameNP from RegularPack.demoRP import nameRP print(nameNP) # 输出NamespacePack print(nameRP) # 输出RegularPack
-
跟普通的包似乎没有任何区别(至少我感知不到)
说在最后
- 初学者(我也算)无需纠结细节
- 只需知道python中的包并不一定要
__init__.py
,over