【发布时间】:2020-04-26 00:02:19
【问题描述】:
给定一个包裹:
package/
├── __init__.py
└── module.py
__init__.py:
from .module import function
module.py:
def function():
pass
可以导入包并打印其命名空间。
python -c 'import package; print(dir(package))'
['__builtins__', ..., 'function', 'module']
问题:
__init__.py 中只导入了function,为什么package 的命名空间包含module?
我原以为package 的命名空间将只包含function 而不是module。这个机制在Documentation中也有提到,
"当使用任何机制加载子模块时(例如 importlib API, import 或 import-from 语句,或内置
__import__()) a 绑定被放置在父模块的命名空间到子模块 对象。”
但没有真正的动力。对我来说,这个选择似乎很奇怪,因为我认为子模块是结构包的实现细节,并且不期望它们成为 API 的一部分,因为结构可以改变。
我还知道“Python 是为成年人所用的”,并且无法真正向用户隐藏任何内容。但我会争辩说,将子模块名称绑定到包的范围会使用户不太清楚什么是 API 的实际部分以及可以更改的内容。
为什么不使用__sub_modules__ 属性让用户可以访问子模块?这个设计决定的原因是什么?
【问题讨论】:
-
您说您将子模块视为实现细节。这不是子模块背后的设计意图;它们可以并且非常普遍地是包的公共接口的一部分。看
collections、numpy、requests、tensorflow、urllib、asyncio等 -
@user2357112supportsMonica 我知道这一点。但同样可以通过显式导入子模块来实现。例如 numpy.linalg:
from . import linalg。我只是觉得奇怪的是from .linalg import dot将linalg绑定到numpy范围。所以我不认为子模块一般不应该是接口的一部分,但我认为它不应该隐式发生。 -
“但没有真正的动力”。它从字面上完全解释了您的情况,但如果您正在寻找原因,则必须浏览邮件列表
标签: python python-3.x python-import python-packaging