Python导入X还是从X导入Y?(性能)

Tom*_*Tom 28 python performance

如果有一个库我将使用至少两种方法,那么下面的性能或内存使用是否有任何差异?

from X import method1, method2
Run Code Online (Sandbox Code Playgroud)

import X
Run Code Online (Sandbox Code Playgroud)

rob*_*rob 37

有区别,因为在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
Run Code Online (Sandbox Code Playgroud)

如您所见,使用表单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
Run Code Online (Sandbox Code Playgroud)

我不知道原因,但似乎表格from x import y看起来像一个函数调用,因此比预期更昂贵; 因此,如果导入的函数只使用一次,则意味着使用起来会更快import x,而如果它被多次使用,则使用起来会更快from x import y.

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

  • 它是虚拟机上的一个操作码.让它在2 Ghz机器上进行10个循环,即**5纳秒**.只读这个句子需要的时间比程序在你一生中可以节省的时间多. (14认同)

Joc*_*zel 9

没有内存或速度差异(整个模块必须以任何一种方式进行评估,因为最后一行可能是Y = something_else).除非您的计算机是从20世纪80年代开始的,否则它无关紧要.

  • 在我的项目中,从 PyQt5 执行 40 次导入会导致启动期间出现 500 毫秒的延迟,我认为这是不可接受的。那是在 SSD 和 i7-4790K 上。正因为如此,我可能会转向 C++,所以是的,这很重要……也许不完全是 OP 问题的上下文,但它表明导入确实会导致性能问题。 (2认同)

DSt*_*man 9

如果您在循环中多次调用函数(数百万次或更多),这可能很重要。做双字典查找最终会累积。下面的示例显示了 20% 的增长。

引用的时间是针对 Win7 64 位机器上的 Python 3.4。(将 Python 2.7 的 range 命令更改为 xrange)。

这个示例高度基于High Performance 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)
Run Code Online (Sandbox Code Playgroud)


hec*_*ckj 5

我不相信有什么真正的区别,并且通常担心很少的内存通常不值得。如果您要强调内存注意事项,那么它很可能会出现在您的代码中。