是什么让Pythons如此快速地追加列表方法?

时间:2016-10-22 11:35:40

标签: python performance

我正在比较在python中将项目附加到列表的不同方法。我在我的计算机上测试过,结果当然会在其他计算机上有所不同。

选项1 :5.80秒只有50,000件商品!

a = []
for i in range(50000):
    a = a + [i]

选项2 :2.27秒10,000,000项

a = []
for i in range(10000000):
    a += [i]

选项3 :1.53秒10,000,000项

a = []
for i in range(10000000):
    a.append(i)

选项1很慢并不奇怪,因为它每次都会创建一个新的列表副本。

使用扩充赋值运算符,选项2的速度要快得多。它会修改原始列表。

但选项3仍然明显更快。我期望使用append()方法和扩充赋值运算符来获得相同的结果。

为什么append()方法仍然比+ =运算符快得多?

PS: 我的python版本:

Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)] on win32

根据taskino的回答,额外的开销是在每次循环迭代中创建一个新的列表对象[i]引起的。这对我来说似乎很合理。我创建了新的测试代码,试图避免在每次迭代中创建一个新对象。是的,它现在更快,但仍然没有使用append()那么快,因为现在我又有额外分配的开销。但我认为它证明了taskinoor的重点。

选项4 :1.91秒10,000,000项 (备选方案2的改进版本)

a = []
b = [0]
for i in range(10000000):
    b[0] = i
    a += b

1 个答案:

答案 0 :(得分:3)

第二种方法仍然需要创建临时列表[i]。看看反汇编的代码:

>>> import dis
>>> def func_2(a, i):
...     a += [i]
... 
>>> def func_3(a, i):
...     a.append(i)
... 
>>> dis.dis(func_2)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                1 (i)
              6 BUILD_LIST               1
              9 INPLACE_ADD         
             10 STORE_FAST               0 (a)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE        
>>> dis.dis(func_3)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_ATTR                0 (append)
              6 LOAD_FAST                1 (i)
              9 CALL_FUNCTION            1
             12 POP_TOP             
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE        
>>> 

第二种方法需要6 BUILD_LIST,但第三种方法不需要config.properties。可能还有其他原因,但这应该是方法3更快的主要原因。