您应该知道的第一件事是 Python 语言不是 ISO 标准。这与 C/C++ 完全不同,这意味着没有“正确”的方式来定义语言行为 - CPython 可能会因为它是这样编码而做某事,而 Jython 可能会反过来做。
关于您的问题,请记住“导入”模块是一个由两部分组成的操作:首先加载模块 - 如果它从未加载过,例如,如果它在 sys.modules 中不可用,那么名称将绑定到该模块在本地命名空间中。
因此:
1) 是的,您可以通过提供适当的命名空间从模块 a 中引用您想要的任何内容,例如,您必须执行类似的操作
BCname = "某事"
而且我认为这在 Python 程序中很少这样做,并且可能被认为是不好的做法,因为它强制“传递 dep” - 如果某些模块 B 实现被重构并且不再依赖于 C,它应该继续提供 C 模块为了满足 A deps。
当然设置 __ all __ 可以防止这种情况发生,一个好的做法可能是将 __ all __ 放在所有模块中,并仅导出您想要真正公开的符号。
2) 是和不是。正在做
import a.b.c.d
在所有模块上执行第一个导入阶段(加载),但第二个只是在 a 上(并且递归地在 b 中相对于 c 等),但链中的所有模块必须由完整的命名空间引用;在这样的导入之后,你可以做
a.something
a.b.something
a.b.c.something
但你不能
c.something
b.something
我必须承认这种用法也很少见。我通常更喜欢“从模块导入某些东西”的导入方式,通常你只需要你需要什么——这种嵌套在库中既不常见,也不常见。
很多时候有“外部包”,仅用于组织,其中包含带有类的模块。很可能上面的a、b、c只是包,而d是真正包含类、函数和其他对象的模块。所以正确的用法是:
from a.b.c.d import name1, name2, name3
我希望这能满足你的好奇心。