我发现了一种新的模式.这种模式是众所周知的还是对它的看法是什么?
基本上,我很难刷新源文件以找出可用的模块导入等等,所以现在,而不是
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__
为模块设置变量,但随后我必须在模块发展时更新它,这对于实际存在于模块中的代码无效.
其次,我很少在我的模块顶部进行一连串的进口,其中一半或更多我不再需要,因为我已经重构了它.最后,我发现这个模式更容易阅读,因为每个引用的名称都在函数体中.
这个问题的(先前)最高投票答案格式很好,但性能绝对错误.让我来证明一下
性能import random def f(): L = [] for i in xrange(1000): L.append(random.random()) for i in xrange(1000): f() $ time python import.py real 0m0.721s user 0m0.412s sys 0m0.020s
def f(): import random L = [] for i in xrange(1000): L.append(random.random()) for i in xrange(1000): f() $ time python import2.py real 0m0.661s user 0m0.404s sys 0m0.008s
如您所见,在函数中导入模块可能更有效.这样做的原因是简单的.它将引用从全局引用移动到本地引用.这意味着,至少对于CPython,编译器将发出LOAD_FAST
指令而不是LOAD_GLOBAL
指令.顾名思义,这些更快.另一个回答者sys.modules
通过在循环的每个迭代中导入来人为地夸大了查看的性能.
通常,最好在顶部导入,但如果您多次访问模块,性能不是原因.原因是人们可以更容易地跟踪模块所依赖的内容,并且这样做与Python Universe的其余部分一致.
这确实有一些缺点.
测试如果您想通过运行时修改来测试模块,可能会使其变得更加困难.而不是做
import mymodule mymodule.othermodule = module_stub
你必须这样做
import othermodule othermodule.foo = foo_stub
这意味着您必须全局修补othermodule,而不是仅仅更改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
这种方法存在一些问题:
打开文件所依赖的模块并不是很明显.
这将混淆要分析的依赖程序,如py2exe
,py2app
等.
您在许多功能中使用的模块怎么样?您最终会得到大量的冗余导入,或者您必须在文件的顶部和一些内部函数中放置一些.
所以...首选的方法是将所有导入放在文件的顶部.我发现如果我的导入很难跟踪,通常意味着我有太多的代码,我最好把它分成两个或更多的文件.
在那里我一些情况下已经发现里面进口的功能是有用的:
处理循环依赖(如果你真的无法避免它们)
平台特定代码
另外:在每个函数中放入导入实际上并不比文件顶部慢.第一次加载每个模块时,它被放入sys.modules
,并且每个后续导入仅花费查找模块的时间,这相当快(不重新加载).
另一个有用的注意事项是from module import *
在Python 3.0中删除了函数内部的语法.
这里简单提一下"删除的语法":
http://docs.python.org/3.0/whatsnew/3.0.html