Python 为什么这种复制列表的方法比其他方法快得多?

Python 为什么这种复制列表的方法比其他方法快得多?,python,performance,list,copy,Python,Performance,List,Copy,我做了这个列表复制实验,发现其中一个时间比其他时间要快得多,就我所知,它确实复制了列表,除非有人能做出其他解释 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

我做了这个列表复制实验,发现其中一个时间比其他时间要快得多,就我所知,它确实复制了列表,除非有人能做出其他解释

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]}

有人能解释一下这里发生了什么吗?

通过在作业中使用
[:]
,您已将左侧列表扩展为与右侧列表具有相同数量的元素。剩下的测试然后重复使用那些额外的元素<代码>d['b']不再为空

换句话说,除了第一次迭代之外,复制操作不必为列表分配更多的索引。这使它更快

您每次都需要使用左侧的列表进行测试。使用来运行适当的时间测试。使用适当大的输入:

>>> 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

在这个特定的测试运行中,从空列表开始实际上要稍微快一点;区别主要在于噪音,但是,重新运行这两个测试会定期交换时间。

d['b'][:]=d['a']
不需要为列表
d['b']
分配内存,因为它已经由上一个操作分配,并且正在重用现有的列表对象。其他人创建一个新列表