Python连接与列表上的附加速度

时间:2014-08-09 09:06:35

标签: python list append concatenation

从interactivepython.org获取此片段:

def test1():  # concat
    l = []
    for i in range(1000):
        l = l + [i]

def test2():  # append
    l = []
    for i in range(1000):
        l.append(i)

concat  6.54352807999 milliseconds
append  0.306292057037 milliseconds

底部块是运行时间。

它表示连接是O(k),其中k是连接列表的"长度"。我不确定这是否意味着您要添加的列表(原始),或者您要添加的列表。但在这两个循环中,您似乎只是每次迭代执行一步。那么为什么追加得更快呢?

2 个答案:

答案 0 :(得分:9)

如果将test1更改为:

def test1():  # concat
    l = []
    for i in range(1000):
        l += [i] 

时间会更接近,你实际上正在做append每次不创建新列表的事情。

In [26]: %timeit test1()
10000 loops, best of 3: 169 µs per loop

In [27]: %timeit test2()
10000 loops, best of 3: 115 µs per loop

如果您在代码中添加print id,则会在test1中看到您每次都在创建一个新对象,但在test2中它始终是相同的列表:

In [41]: test1()
139758194625352
139758206001808
139758205966960
139758194625352
139758206001808
139758205966960
139758194625352
139758206001808
139758205966960
139758194625352
Out[41]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [42]: test2()
139758206002600
139758206002600
139758206002600
139758206002600
139758206002600
139758206002600
139758206002600
139758206002600
139758206002600
139758206002600
Out[42]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

答案 1 :(得分:3)

因为连接必须在每次迭代时构建 new 列表对象:

每次创建新列表比将一个项目添加到现有列表要贵得多。

在幕后,.append()将在C数组中填充预先分配的索引,并且只定期地使列表对象必须增长该数组。另一方面,构建新的列表对象必须每次分配一个C数组