13

我有两个相关的 Python 'import' 问题。它们很容易测试,但我想要的是语言定义的而不是特定于实现的答案,而且我也对风格/约定感兴趣,所以我在这里问。

1)

如果模块 A 导入模块 B,模块 B 导入模块 C,模块 A 中的代码可以在没有显式导入的情况下引用模块 C 吗?如果是这样,我认为这是不好的做法是否正确?

2)

如果我导入模块 ABC,是否也导入模块 A 和 AB?如果是这样,按照惯例,明确的更好import A; import A.B; import A.B.C吗?

4

2 回答 2

13

您应该知道的第一件事是 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

我希望这能满足你的好奇心。

于 2009-12-16T22:20:10.757 回答
11

艾伦给出了一个很好的答案,但我想为你的问题 1 补充一点,这取决于你所说的“进口”是什么意思。

如果您使用from C import x语法,则xB. 如果A你这样做import B,你可以访问xfrom Aas B.x

这并不是什么不好的做法,而是可能令人困惑,并且会使调试等变得更加困难,因为您不一定知道对象来自哪里。

于 2009-12-16T22:24:23.483 回答