从库的深处导入含子模块的模块
在我们办公室,有一个以公司名字命名的库,里面有一些子库,基本上是按项目分类的,每个子库里可能还有更多的模块或库。我们使用的是Django,这让我们的层级结构变得更复杂了...
我对以下几种导入方式的区别有点困惑:
1:
import company.productline.specific.models, company.productline.base.models specific, base = company.productline.specific, company.productline.base2:
import company.productline.specific.models, company.productline.base.models from company.productline import specific, base
3:
from company.productline import specific, base import company.productline.specific.models, company.productline.base.models
第一种方式是不是只导入了 models
呢?那 specific
和 base
在当前的命名空间中是什么呢?
如果先导入子模块,然后再导入包含它们的库,模块的初始化会发生什么呢?
也许最简洁的方式是最后一种,至少对我来说很清楚,我先导入了这两个模块,并且直接把它们的名字放到了当前的命名空间中,第二次导入则是把 model
子模块添加到刚刚导入的两个模块里。
另一方面,(1) 让我只导入内部模块,并且可以用一种简洁而清晰的方式来引用它们(specific.models
和 base.models
)。
我不太确定这是不是个问题,但我很想看看大家的评论。
2 个回答
上面这三个例子在实际使用中是等价的。不过,它们都有点奇怪。没有必要这样做:
from company.productline import specific
还有
import company.productline.specific.models
通常情况下,你可以在第一次导入后直接通过 specific.models
来访问模型。
在这种情况下,做以下操作似乎是合理的:
from company.productline import base
from company.productline import specific
然后你可以像这样访问它们:base.models
、specific.whatever
,等等。如果“specific”是一个模块,你还需要在 __init__.py
文件中做一个 import model
,这样才能访问到 specific.module
。
我深入研究了一下,使用了这个看起来没什么用的包:
A:(__init__.py: print 'importing A',
B:(__init__.py: print 'importing B',
C1:(__init__.py: print 'importing C1',
D:(__init__.py: print 'importing D'))
C2:(__init__.py: print 'importing C2',
D:(__init__.py: print 'importing D'))))
注意到 C1
和 C2
各自包含两个不同的模块,它们在各自的命名空间中都叫 D
。我需要这两个模块,但我不想每次都写完整的路径 A.B.C1.D 和 A.B.C2.D,因为那样看起来太繁琐了。而且我不能把它们都放在当前的命名空间里,因为一个会覆盖另一个。而且,我不想改它们的名字。我想要的是在当前命名空间中同时使用 C1
和 C2
,并加载这两个 D
模块。
哦,对了:我还希望代码能看起来清晰易懂。
我尝试了两种形式:
from A.B import C1
还有一种看起来更丑的形式:
import A.B.C1
C1 = A.B.C1
我得出的结论是,它们是等价的:
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) [GCC 4.3.3] on linux2
>>> from A.B import C1
importing A
importing B
importing C1
>>> C1
<module 'A.B.C1' from 'A/B/C1/__init__.pyc'>
>>>
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) [GCC 4.3.3] on linux2
>>> import A.B.C1
importing A
importing B
importing C1
>>> C1=A.B.C1
>>> C1
<module 'A.B.C1' from 'A/B/C1/__init__.pyc'>
>>>
导入包 C1 或 C2 并不会自动导入它们包含的模块,仅仅因为它们在那里。而且很遗憾,像 from A.B import C1.D
这样的写法在语法上是不被接受的:这本来是个很简洁的写法。
另一方面,如果我愿意的话,可以在 A.B.C1.__init__.py
中做到这一点。所以如果我在 A.B.C1
的 __init__.py
文件中加上 import D
这一行,结果会是这样的:
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) [GCC 4.3.3] on linux2
>>> from A.B import C1
importing A
importing B
importing C1
importing D
>>>
导入包含的模块最好在包初始化的最后进行。
考虑到这些情况,以及一些特定的 Django 行为(这使得在导入包时自动 import models
变得困难或不可能),我觉得我更喜欢第三种风格。