我发现了一种新的模式。这种模式是众所周知的吗?或者对此有什么看法?
基本上,我很难上下清理源文件来找出哪些模块导入是可用的等等,所以现在,不是
import foo
from bar.baz import quux
def myFunction():
foo.this.that(quux)
我将所有的导入移到实际使用它们的函数中,如下所示:
def myFunction():
import foo
from bar.baz import quux
foo.this.that(quux)
这做了几件事。首先,我很少意外地用其他模块的内容污染我的模块。我可以为模块设置__all__
变量,但是随着模块的发展,我必须更新它,这对实际存在于模块中的代码的名称空间污染没有帮助。
其次,我很少在我的模块顶部有一长串的导入,其中一半或更多我不再需要,因为我已经重构了它。最后,我发现这个模式更容易阅读,因为每个引用的名称都在函数体中。
发布于 2009-01-25 03:24:50
这确实有一些缺点。
测试
如果您想通过运行时修改来测试您的模块,这可能会使它变得更加困难。而不是做
import mymodule
mymodule.othermodule = module_stub
你要做的是
import othermodule
othermodule.foo = foo_stub
这意味着您必须全局修补其他模块,而不是仅仅更改mymodule中的引用所指向的内容。
依赖关系跟踪
这使得您的模块依赖于哪些模块并不明显。如果您使用许多第三方库或正在重新组织代码,这尤其令人恼火。
我不得不维护一些使用内联导入的遗留代码,这使得代码非常难以重构或重新打包。
关于性能的说明
因为python缓存模块的方式,所以不会对性能造成影响。实际上,由于模块位于本地名称空间中,因此在函数中导入模块会带来一些性能上的好处。
顶级导入
import random
def f():
L = []
for i in xrange(1000):
L.append(random.random())
for i in xrange(10000):
f()
$ time python test.py
real 0m1.569s
user 0m1.560s
sys 0m0.010s
在函数体内导入
def f():
import random
L = []
for i in xrange(1000):
L.append(random.random())
for i in xrange(10000):
f()
$ time python test2.py
real 0m1.385s
user 0m1.380s
sys 0m0.000s
发布于 2009-01-25 03:32:29
需要注意的另一件有用的事情是,在Python3.0中删除了函数内部的from module import *
语法。
在这里的“已删除的语法”中有一个简短的提及:
发布于 2009-01-25 16:10:16
我建议您尽量避免from foo import bar
导入。我只在包中使用它们,其中模块的拆分是一个实现细节,而且不会有太多模块。
在导入包的所有其他地方,只需使用import foo
,然后通过全名foo.bar
引用它。通过这种方式,您总是可以知道某个元素来自何处,而不必维护导入元素的列表(实际上,这将始终是过时的,并且导入不再使用的元素)。
如果foo
是一个很长的名称,您可以使用import foo as f
简化它,然后编写f.bar
。这仍然比维护所有的from
导入方便和明确得多。
https://stackoverflow.com/questions/477096
复制相似问题