Python 导入 X 还是从 X 导入 Y? (表现)

问题描述 投票:0回答:4

如果我要使用至少两种方法的库,以下方法之间的性能或内存使用情况是否有任何差异?

from X import method1, method2

import X
python performance
4个回答
55
投票

有区别,因为在

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

也就是说,像往常一样,我建议您不要遵循这些知识来决定如何导入模块和函数,因为这只是一些过早的优化。
就我个人而言,我认为在很多情况下,显式命名空间更具可读性,我建议您也这样做:使用您自己的审美感:-)


12
投票

如果您在循环中多次调用某个函数(数百万次或更多),那就很重要了。 进行双字典查找最终会累积。 下面的示例显示增加了 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)

12
投票

内存或速度没有显着差异(必须以任何方式评估整个模块,因为最后一行可能是

Y = something_else
)。除非你的电脑是 20 世纪 80 年代的,否则没关系。


7
投票

我不认为有任何真正的区别,而且通常担心那么少量的内存通常是不值得的。如果您要迫切考虑内存问题,那么它更有可能出现在您的代码中。

© www.soinside.com 2019 - 2024. All rights reserved.