迭代vs List连接
因此,有两种方法可以创建列表并将第二个列表的成员添加到第一个列表中。 你可以使用列表连接,或者你可以迭代它。 您可以:
for obj in list2:
list1.append(obj)
或者您可以:
list1 = list1 + list2
要么
list1 += list2
我的问题是:哪个更快,为什么? 我使用两个非常大的列表(10000个以上的对象)测试了这种情况,似乎迭代方法比列表级联快得多(如在l1 = l1 + l2中)。 为什么是这样? 有人可以解释吗?
append
逐个添加每个项目,这是导致其缓慢的原因,以及要append
的重复函数调用。
然而在这种情况下, +=
运算符不是 +
语法糖。 +=
操作符实际上并不创建新列表,然后将其重新分配,它修改了左侧操作数。 使用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
+=
快得多(约500x)
你也有列表的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
比迭代更快,因为它是内置列表方法并且已经过优化。 逻辑上相当于反复追加,但实施方式不同。
+=
比extend
速度快,因为它可以修改列表,知道列表要多大且不需要重复函数调用。 它假定你用另一个列表/元组追加你的列表
我运行了下面的代码
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
你测量错误 ; 迭代和调用append
多次比做一次调用要慢得多,因为许多函数调用的开销(至少在cpython中)与实际的列表操作相关的任何事情都相形见绌,如下所示,Linux上的cPython 2.7.5 64位:
$ 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方法的开销。