Python导入机制

Cor*_*sky 12 python import coding-style module conventions

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

1)

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

2)

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

Ala*_*oni 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 
Run Code Online (Sandbox Code Playgroud)

在所有模块上执行第一个导入阶段(加载),但第二个只在a上(并且,递归地,在b中相对于c等),但链中的所有模块必须由完整命名空间引用; 经过这样的导入,你可以做到

a.something
a.b.something
a.b.c.something
Run Code Online (Sandbox Code Playgroud)

但你做不到

c.something
b.something
Run Code Online (Sandbox Code Playgroud)

我必须承认,这种用法也很少见; 我通常更喜欢"从模块导入某种东西"的方式导入,通常你只是问你需要什么 - 这种嵌套在图书馆中既不常见,也不常见.

很多时候都有"外包装",只用于组织,它用于保存带有类的模块.上面的a,b,c很可能只是包,而d是一个真正保存类,函数和其他对象的模块.所以正确的用法是:

from a.b.c.d import name1, name2, name3
Run Code Online (Sandbox Code Playgroud)

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


Dan*_*man 11

艾伦给出了一个很好的答案,但我想补充一点,问题1取决于你对"进口"的意思.

如果使用from C import x语法,则可x在命名空间中使用B.如果A你在那里import B,你有权访问as .xAB.x

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