我有两个相关的Python导入问题。它们很容易测试,但我想要的是语言定义的而不是实现特定的答案,而且我对样式/约定也很感兴趣,所以我在这里问。Python导入机制
1)
如果模块A导入模块B和模块B模块进口C,可以在模块没有明确的进口代码的引用模块C?如果是这样,我认为这是不好的做法是正确的吗?
2)
如果我导入模块A.B.C,是否进口模块A和A·B以及?如果是这样,是否明确规定import A; import A.B; import A.B.C
?
我有两个相关的Python导入问题。它们很容易测试,但我想要的是语言定义的而不是实现特定的答案,而且我对样式/约定也很感兴趣,所以我在这里问。Python导入机制
1)
如果模块A导入模块B和模块B模块进口C,可以在模块没有明确的进口代码的引用模块C?如果是这样,我认为这是不好的做法是正确的吗?
2)
如果我导入模块A.B.C,是否进口模块A和A·B以及?如果是这样,是否明确规定import A; import A.B; import A.B.C
?
您应该知道的第一件事是Python语言不是ISO标准。这与C/C++有很大不同,这意味着没有“正确”的方式来定义语言行为--CPython可能会做某些事情,只是因为它是以这种方式编码的,而Jython可能会这样做。
关于您的问题,请记住,“导入”模块是一个由两部分组成的操作:首先装载模块 - 如果它从未如此,例如如果它在sys.modules中不可用,那么名称将绑定到本地名称空间中的该模块。
因此:
1)是,可以通过提供适当的命名空间,例如引用任何你从模块一个想你必须做一些像
BCname =“东西”
而且我认为这是在Python程序很少做,可以被认为是不好的做法,因为它迫使“传递DEP” - 如果一些模块B实现被重构并且不再依赖于C,它应该继续提供C模块来满足A代价。
课程设置__ __都可以防止这种情况,和一个很好的做法可能是把所有__ __在所有的模块,并导出只是你想成为真正的公共符号。 2)是和不是。做
import a.b.c.d
执行所有模块上的第一导入阶段(装载),但第二只是一个(并且递归地,在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-16 23:03:00
虽然不是ISO,但有一个定义“正确”行为的Python语言参考,包括导入:http://docs.python.org/reference/simple_stmts.html#the-import-statement 语言参考指出CPython的实现细节,但其目标是成为该语言的通用规范,因此它不是全部依赖于实现。 – 2009-12-17 09:09:10
艾伦给出了一个很好的答案,但我想补充说,对于你的问题1,这取决于你的意思是“进口”。
如果使用from C import x
语法,则在B
的名称空间中可用x
。如果在A
中,然后您做import B
,您将有权访问x
从A
作为B.x
。
这不是太糟糕的做法,因为可能会让人困惑,并且会使调试更困难,因为您不一定知道对象来自哪里。
这是一个有用的说明,谢谢。我一直认为'import'与Java风格的软件包导入类似,但显然这种相似性仅仅是肤浅的。 – 2009-12-16 23:05:04
如果令人困惑,是不是有足够的理由称之为坏习惯?应该明白什么代码只是通过阅读它恕我直言。 – jjpe 2015-04-14 18:06:27
“语言定义的而不是实现特定的”你是说Python实现有些不同吗?你知道哪些具体的差异? AFAIK没有。 – 2009-12-16 21:49:45
也许没有任何区别,但是规范未定义的任何内容都取决于实现。 Python文档散布着关于CPython实现细节的警告,这些细节可能不适用于其他实现。 – 2009-12-16 21:52:38