如果我要使用至少两种方法的库,以下方法之间的性能或内存使用情况是否有任何差异?
from X import method1, method2
和
import X
有区别,因为在
import x
版本中有两次名称查找:一个是模块名称,第二个是函数名称;另一方面,使用 from x import y
,您只有一次查找。
使用 dis 模块你可以很好地看到这一点:
import random
def f_1():
random.seed()
dis.dis(f_1)
0 LOAD_GLOBAL 0 (random)
3 LOAD_ATTR 0 (seed)
6 CALL_FUNCTION 0
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
from random import seed
def f_2():
seed()
dis.dis(f_2)
0 LOAD_GLOBAL 0 (seed)
3 CALL_FUNCTION 0
6 POP_TOP
7 LOAD_CONST 0 (None)
10 RETURN_VALUE
如您所见,使用
from x import y
形式会更快一些。
另一方面,
import x
比from x import y
便宜,因为名称查找更少;我们看一下反汇编代码:
def f_3():
import random
dis.dis(f_3)
0 LOAD_CONST 1 (-1)
3 LOAD_CONST 0 (None)
6 IMPORT_NAME 0 (random)
9 STORE_FAST 0 (random)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE
def f_4():
from random import seed
dis.dis(f_4)
0 LOAD_CONST 1 (-1)
3 LOAD_CONST 2 (('seed',))
6 IMPORT_NAME 0 (random)
9 IMPORT_FROM 1 (seed)
12 STORE_FAST 0 (seed)
15 POP_TOP
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
我不知道原因,但看起来
from x import y
的形式看起来像函数调用,因此比预期的更昂贵;因此,如果导入的函数仅使用一次,则意味着使用速度会更快import x
,而如果多次使用,则使用速度会更快from x import y
。
也就是说,像往常一样,我建议您不要遵循这些知识来决定如何导入模块和函数,因为这只是一些过早的优化。
就我个人而言,我认为在很多情况下,显式命名空间更具可读性,我建议您也这样做:使用您自己的审美感:-)
如果您在循环中多次调用某个函数(数百万次或更多),那就很重要了。 进行双字典查找最终会累积。 下面的示例显示增加了 20%。
引用的时间适用于 Win7 64 位计算机上的 Python 3.4。 (对于 Python 2.7,将范围命令更改为 xrange)。
这个示例高度基于本书高性能Python,尽管他们的本地函数查找更好的第三个示例似乎不再适合我。
import math
from math import sin
def tight_loop_slow(iterations):
"""
>>> %timeit tight_loop_slow(10000000)
1 loops, best of 3: 3.2 s per loop
"""
result = 0
for i in range(iterations):
# this call to sin requires two dictionary lookups
result += math.sin(i)
def tight_loop_fast(iterations):
"""
>>> %timeit tight_loop_fast(10000000)
1 loops, best of 3: 2.56 s per loop
"""
result = 0
for i in range(iterations):
# this call to sin only requires only one lookup
result += sin(i)
内存或速度没有显着差异(必须以任何方式评估整个模块,因为最后一行可能是
Y = something_else
)。除非你的电脑是 20 世纪 80 年代的,否则没关系。
我不认为有任何真正的区别,而且通常担心那么少量的内存通常是不值得的。如果您要迫切考虑内存问题,那么它更有可能出现在您的代码中。