为什么Python 3比Python 2慢很多?[重复]

发布于 2021-01-29 15:06:57

这个问题已经在这里有了答案

Python 3枚举比Python 2慢是有原因的吗? (2个答案)

5年前关闭。

我一直在试图理解为什么在某些情况下Python 3与Python 2相比实际上要花费很多时间,以下是我从python 3.4到python
2.7进行验证的几种情况。

注意:我已经经历了一些问题,例如,为什么Python3中没有xrange函数?

python2相比,在python3中循环并比python2慢得多,
并且在Python3中使用相同的代码也比Python2慢,但是我感到我没有得到这个问题背后的实际原因。

我已经尝试了这段代码来展示它是如何发挥作用的:

MAX_NUM = 3*10**7

# This is to make compatible with py3.4.
try:
    xrange
except:
    xrange = range


def foo():
    i = MAX_NUM
    while i> 0:
        i -= 1

def foo_for():
    for i in xrange(MAX_NUM):
        pass

当我尝试使用py3.4和py2.7运行该程序时,得到的结果如下。

注意:这些统计信息来自64 bit带有2.6Ghz处理器的计算机,并使用time.time()单循环计算时间。

Output : Python 3.4
-----------------
2.6392083168029785
0.9724123477935791

Output: Python 2.7
------------------
1.5131521225
0.475143909454

我真的不认为已将2.7whilexrange3.4应用于更改,或从2.7更改为3.4,我知道range它已经开始xrange在py3.4中起作用,但正如文档所述

range()现在的行为就像以前一样xrange(),只是它可以使用任意大小的值。后者不再存在。

这意味着从xrangeto更改range非常等同于名称更改,但是可以使用任意值。

我也验证了反汇编的字节码。

下面是该函数的反汇编字节码foo()

Python 3.4:
---------------

 13           0 LOAD_GLOBAL              0 (MAX_NUM)
              3 STORE_FAST               0 (i)

 14           6 SETUP_LOOP              26 (to 35)
        >>    9 LOAD_FAST                0 (i)
             12 LOAD_CONST               1 (0)
             15 COMPARE_OP               4 (>)
             18 POP_JUMP_IF_FALSE       34

 15          21 LOAD_FAST                0 (i)
             24 LOAD_CONST               2 (1)
             27 INPLACE_SUBTRACT
             28 STORE_FAST               0 (i)
             31 JUMP_ABSOLUTE            9
        >>   34 POP_BLOCK
        >>   35 LOAD_CONST               0 (None)
             38 RETURN_VALUE

python 2.7
-------------

 13           0 LOAD_GLOBAL              0 (MAX_NUM)
              3 STORE_FAST               0 (i)

 14           6 SETUP_LOOP              26 (to 35)
        >>    9 LOAD_FAST                0 (i)
             12 LOAD_CONST               1 (0)
             15 COMPARE_OP               4 (>)
             18 POP_JUMP_IF_FALSE       34

 15          21 LOAD_FAST                0 (i)
             24 LOAD_CONST               2 (1)
             27 INPLACE_SUBTRACT    
             28 STORE_FAST               0 (i)
             31 JUMP_ABSOLUTE            9
        >>   34 POP_BLOCK           
        >>   35 LOAD_CONST               0 (None)
             38 RETURN_VALUE

下面是该函数的反汇编字节码foo_for()

Python: 3.4

 19           0 SETUP_LOOP              20 (to 23)
              3 LOAD_GLOBAL              0 (xrange)
              6 LOAD_GLOBAL              1 (MAX_NUM)
              9 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             12 GET_ITER
        >>   13 FOR_ITER                 6 (to 22)
             16 STORE_FAST               0 (i)

 20          19 JUMP_ABSOLUTE           13
        >>   22 POP_BLOCK
        >>   23 LOAD_CONST               0 (None)
             26 RETURN_VALUE


Python: 2.7
-------------

 19           0 SETUP_LOOP              20 (to 23)
              3 LOAD_GLOBAL              0 (xrange)
              6 LOAD_GLOBAL              1 (MAX_NUM)
              9 CALL_FUNCTION            1
             12 GET_ITER            
        >>   13 FOR_ITER                 6 (to 22)
             16 STORE_FAST               0 (i)

 20          19 JUMP_ABSOLUTE           13
        >>   22 POP_BLOCK           
        >>   23 LOAD_CONST               0 (None)
             26 RETURN_VALUE

如果我们比较两个字节码,它们将产生相同的反汇编字节码。

现在,我想知道从2.7到3.4的什么变化实际上导致给定代码段中执行时间的巨大变化。

关注者
0
被浏览
78
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    不同之处在于int类型的实现。蟒3.X使用任意大小的整数类型(long在2.X)排他地,而在Python
    x为值高达sys.maxint更简单的int类型被用于使用一个简单的Clong引擎盖下。

    将循环限制为 long 整数后,Python 3.x会更快:

    >>> from timeit import timeit
    >>> MAX_NUM = 3*10**3
    >>> def bar():
    ...     i = MAX_NUM + sys.maxsize
    ...     while i > sys.maxsize:
    ...         i -= 1
    ...
    

    Python 2:

    >>> timeit(bar, number=10000)
    5.704327821731567
    

    Python 3:

    >>> timeit(bar, number=10000)
    3.7299320790334605
    

    我用sys.maxsize作为sys.maxint从Python 3的下降,但整数值基本相同。

    因此,Python 2中的速度差异仅限于第一个(2 63)-64位为1整数,(2 31)-32位系统为1整数。

    由于您无法在Python 2上使用该long类型xrange(),因此我没有对该函数进行比较。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看