Python 代码提速(注意深拷贝和列表操作)
用python写了个labeling算法,速度着实慢,心想python也不至于这么慢呀,如何提高一下代码速度。
提速前的原始代码速度:
可以看到几个问题:
● deepcopy 是主要耗时部分,占了大部分时间
● list.remove 列表操作太费时间
1.深拷贝deepcopy
这里为了方便我直接用的copy包里的deepcopy,考虑到python深拷贝主要涉及列表,这里对比几种列表拷贝的方式。注意前两种方法是只深拷贝一层。
from copy import deepcopy
from time import time
from tqdm import trange
x = list(range(1,10))
y1,y2,y3 = [], [], []
for i in trange(1,10):
li = list(range(10**i))
#方式1:直接复制
st1 = time()
temp1 = [i for i in li]
end1 = time()
y1.append(end1-st1)
#方式2:直接复制
st2 = time()
temp2 = li[:]
end2 = time()
y2.append(end2-st2)
#方式3:深拷贝
st3 = time()
temp3 = deepcopy(li)
end3 = time()
y3.append(end3-st3)
plt.plot(x,y1,color="b",label='copy 1')
plt.plot(x,y2,color="g",label='copy 2')
plt.plot(x,y3,color="r",label='deepcopy')
plt.legend()
结果:
结论: python 不同深拷贝速度,deepcopy极慢,使用时需要注意;查了一下,deepcopy包实现的是纯纯深拷贝,即无论多少层都完全拷贝,所以速度极慢,其实在日常使用中我们并不需要那么深的拷贝,谁会列表套列表套列表… 一般,如果嵌套不深,一层拷贝也足够使用了,所以推荐使用前两种拷贝方式。
2.list操作
将4种list常用的操作计时统计:
'python list的四种操作'
from time import time
a = list(range(200000))
s1 = time()
for i in range(len(a)):
a.remove(i)
t1 = time()-s1
a = list(range(200000))
s2 = time()
for i in range(len(a)):
del a[0]
t2 = time()-s2
s3 = time()
a = list(range(200000))
for i in range(200000):
a.pop(-1)
t3 = time()-s3
s4 = time()
a = []
for i in range(200000):
a.append(1)
t4 = time()-s4
print('remove time cost:',t1)
print('del time cost:',t2)
print('pop time cost:',t3)
print('append time cost:',t4)
结果:
结论: append和pop最快,del和remove虽然方便但速度着实慢,将近2个数量级的差距,这意味着如果算法稍微复杂一些,重复调用次数多了以后光list操作就要占据很大半时间,建议尽量用append和pop。有的时候需要删除列表一些元素,使用pop不太方便,可以考虑新建一个列表,将元素挨个append回来。
优化后的代码
优化后的代码效果立竿见影,提升10倍!!!
平时写代码不太注意,怎么方便怎么来,算法稍微复杂一点时间控制不住了,日常代码还是需要注意一下,虽然python各种包方便但稍不注意坑还是多。深拷贝尽量自己写,列表尽量少用.append和.pop()。