我有两个相关的 Python“导入”问题。它们很容易测试,但我想要的答案是语言定义的而不是特定于实现的,而且我也对风格/惯例感兴趣,所以我在这里问。
1)
如果模块 A 导入模块 B,模块 B 导入模块 C,模块 A 中的代码是否可以在不显式导入的情况下引用模块 C?如果是这样,我认为这是不好的做法是否正确?
2)
如果我导入模块 A.B.C,是否也会导入模块 A 和 A.B?如果是这样,按照惯例,显式 import A 是否更好?进口A.B;导入 A.B.C
?
最佳答案
您应该知道的第一件事是 Python 语言不是 ISO 标准。这与 C/C++ 有很大不同,它意味着没有“正确”的方式来定义语言行为 - CPython 可能会做一些事情只是因为它是以这种方式编码的,而 Jython 可能会做相反的事情。
关于您的问题,请记住“导入”模块是一个分为两部分的操作:首先加载模块——如果它从未加载过,例如如果它在 sys.modules 中不可用,则名称将绑定(bind)到本地命名空间中的该模块。
因此:
1) 是的,您可以通过提供适当的命名空间从模块 a 引用任何您想要的内容,例如你必须做类似的事情
B.C.name = "某物"
而且我认为在 Python 程序中很少这样做,并且可以被认为是不好的做法,因为它强制执行“传递依赖”——如果某些模块 B 实现被重构并且不再依赖于 C,它应该继续提供C 模块只是为了满足 A 部门。
当然,设置 __all __ 可以防止这种情况,一个好的做法可能是将 __all __ 放在所有模块中,并导出仅您想要真正公开的符号。 p>
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
希望这能满足您的好奇心。
关于Python 导入机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1917958/