Python导入机制

时间:2009-12-16 21:42:00

标签: python coding-style import module conventions

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

1)

如果模块A导入模块B,而模块B导入模块C,是否可以在模块A参考模块C中编码而无需显式导入?如果是这样,我认为这是不好的做法我是否正确?

2)

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

2 个答案:

答案 0 :(得分:12)

您应该知道的第一件事是Python语言不是ISO标准。这与C / C ++有很大不同,它意味着没有“正确”的方式来定义语言行为--CPython可能只是因为它是以这种方式编码而做的,而Jython可能会反过来。

关于你的问题,记住“导入”模块是一个由两部分组成的操作:首先加载模块 - 如果它从未被加载过,例如如果它在sys.modules中不可用,那么名称将绑定到本地名称空间中的该模块。

因此:

1)是的,您可以通过提供适当的命名空间来引用模块a中的任何内容,例如:你必须做类似

的事情

B.C.name =“something”

我认为这在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

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

答案 1 :(得分:11)

Alan给出了一个很好的答案,但我想补充一点,问题1取决于你对“进口”的意思。

如果您使用from C import x语法,则x的命名空间中将显示B。如果您在Aimport B,则 x A作为B.x访问{/ 1}}。

这并不是一个可能令人困惑的糟糕做法,并且会使调试等变得更难,因为你不一定知道对象来自哪里。