我已经运行了这个列表复制实验,并发现其中一个时间比其他时间快得多,据我所知它复制列表,除非有人能解释其他情况?
import time
def test(d):
s = time.time()
for i in range(20000000):
d['b'] = d['a'].copy()
e = time.time()
print (".copy(): "+str(e-s))
s = time.time()
for i in range(20000000):
d['b'][:] = d['a']
e = time.time()
print ("[:] on left: "+str(e-s))
s = time.time()
for i in range(20000000):
d['b'] = d['a'][:]
e = time.time()
print ("[:] on right: "+str(e-s))
d = {'a': [1,2,3,4],
'b': []}
test(d)
结果:
.copy(): 4.150316476821899
[:] on left: 2.535377025604248
[:] on right: 4.140159606933594
要证明左边的[:]
是复制吗?
d['b'][:] = d['a']
del d['a'][1]
d['a'][0] = "testing"
print (d)
打印:
{'a': ['testing', 3, 4], 'b': [1, 2, 3, 4]}
有人能解释一下这里发生了什么吗?
答案 0 :(得分:4)
通过在作业中使用[:]
,您已将左侧列表展开为与右侧列表具有相同数量的元素。其余的测试然后重新使用那些额外的元素; d['b']
不再是空的!
换句话说,对于除第一次迭代之外的所有内容,该复制操作不必为列表分配更多索引。这使它更快。
每次都需要在左侧测试空列表。使用timeit
module进行正确的时间试验。使用适当的大输入:
>>> timeit('a = []; a[:] = b', 'from __main__ import testlist as b')
2.430507270000817
>>> timeit('a = b[:]', 'from __main__ import testlist as b')
2.5209442199993646
>>> timeit('a = b.copy()', 'from __main__ import testlist as b')
2.5766620540016447
分配更多空间实际上并不需要花费那么多时间;你只能看到小清单的效果:
>>> timeit('a[:] = b', 'a = [1, 2, 3, 4]; b = a[:]', number=10000000)
0.7304684859991539
>>> timeit('a = []; a[:] = b', 'a = [1, 2, 3, 4]; b = a[:]', number=10000000)
0.9908717719954439
(注意,这里的迭代次数已从100万增加到1000万)。
对于大型名单,差异大多没有实际意义:
>>> timeit('a[:] = b', 'from __main__ import testlist as b; a = b[:]')
2.4996446009972715
>>> timeit('a = []; a[:] = b', 'from __main__ import testlist as b')
2.4407932980029727
在这个特定的测试运行中,以空列表开头实际上稍快一些;差别主要是噪音,但是重新运行这两项测试会定期交换时间。
答案 1 :(得分:1)
d['b'][:] = d['a']
不需要为列表d['b']
分配内存,因为它已由前一个操作分配,并且正在重用现有列表对象。其他人创建了一个新列表。