迭代vs列表连接

时间:2013-07-04 23:51:06

标签: python profiling performance

因此,有两种方法可以获取列表并将第二个列表的成员添加到第一个列表中。您可以使用列表连接,也可以迭代它。你可以:

for obj in list2:
    list1.append(obj)

或者你可以:

list1 = list1 + list2

list1 += list2

我的问题是:哪个更快,为什么?我使用两个非常大的列表(超过10000个对象)对此进行了测试,似乎迭代方法比列表连接快得多(如l1 = l1 + l2)。为什么是这样?谁能解释一下?

3 个答案:

答案 0 :(得分:15)

append一次添加一个项目,这是其缓慢的原因,以及对append的重复函数调用。

然而在这种情况下,+=运算符<{1}}的 语法糖。 +运算符实际上并不创建新列表然后将其分配回来,它会修改左侧操作数。使用+=使用10,000次时非常明显。

timeit

>>> timeit.timeit(stmt="l = l + j", setup="l=[1,2,3,4]; j = [5,6,7,8]", number=10000) 0.5794978141784668 >>> timeit.timeit(stmt="l += j", setup="l=[1,2,3,4]; j = [5,6,7,8]", number=10000) 0.0013298988342285156 要快得多(约500倍)

您还可以使用+=方法查找列表,这些方法可以附加extend

之类的任何可迭代(不仅仅是其他列表)
l.extend(l2)

逻辑上相当于追加,但你可以看得快得多。

所以解释一下: 迭代比>>> timeit.timeit(stmt="l.extend(j)", setup="l=[1,2,3,4]; j = [5,6,7,8]", number=10000) 0.0016009807586669922 >>> timeit.timeit(stmt="for e in j: l.append(e)", setup="l=[1,2,3,4]; j = [5,6,7,8]", number=10000) 0.00805807113647461 快,因为+必须构建一个完整的新列表

+比迭代更快,因为它是内置列表方法并且已经过优化。逻辑上等同于重复附加,但实现方式不同。

extend+=快,因为它可以修改列表,知道列表必须有多大,而不需要重复的函数调用。它假设您将列表附加到另一个列表/元组

答案 1 :(得分:0)

我运行了以下代码

l1 = list(range(0, 100000))
l2 = list(range(0, 100000))

def t1():
    starttime = time.monotonic()
    for item in l1:
        l2.append(item)
    print(time.monotonic() - starttime)

l1 = list(range(0, 100000))
l2 = list(range(0, 100000))

def t2():
    starttime = time.monotonic()
    global l1
    l1 += l2
    print(time.monotonic() - starttime)

并得到了这个,它说添加列表(+ =)更快。

0.016047026962041855

0.0019438499584794044

答案 2 :(得分:0)

你的错误;迭代和多次调用append比一次​​调用慢得多,因为许多函数调用的开销(至少在cpython中)使得与实际列表操作有关的任何事情都相形见绌,如cPython 2.7所示。 .5在Linux x64上:

$ python -m timeit -s 'x = range(10000);y = range(10000)' 'for e in y:x.append(e)'
100 loops, best of 3: 2.56 msec per loop
$ python -m timeit -s 'x = range(10000);y = range(10000)' 'x = x + y'
100 loops, best of 3: 8.98 msec per loop
$ python -m timeit -s 'x = range(10000);y = range(10000)' 'x += y'
10000 loops, best of 3: 105 usec per loop
$ python -m timeit -s 'x = range(10000);y = range(10000)' 'x.extend(y)'
10000 loops, best of 3: 107 usec per loop

请注意x = x + y创建列表的第二个副本(至少在cPython中)。 x.extend(y)及其表兄x += y执行与多次调用append相同的操作,只是没有实际调用Python方法的开销。