我有一个Python程序,它从文件中读取行并将它们放入字典中。简单来说,它看起来像这样:
我发现完成这个任务需要好几个小时。
然后,我对程序进行了一些微小的修改:
在我的笔记本电脑(mac pro 2013中期,OS X 10.9.5,cpython 2.7.10)上,它的输出为:
受juanpa.arrivillaga评论的启发,我对第二个循环进行了一些修改:
更改后,现在第二个循环需要19秒才能完成。因此,正如juanpa.arrivillaga所说,这似乎只是一个优化问题。
data = {'file_name':''}
with open('file_name') as in_fd:
for line in in_fd:
data['file_name'] += line
我发现完成这个任务需要好几个小时。
然后,我对程序进行了一些微小的修改:
data = {'file_name':[]}
with open('file_name') as in_fd:
for line in in_fd:
data['file_name'].append(line)
data['file_name'] = ''.join(data['file_name'])
它只用了几秒钟就完成了。
我认为它的+=
使程序变慢了,但实际上并不是这样。请看以下测试结果。
我知道我们可以使用列表的append和join来提高连接字符串的性能。但我从未想过在添加和赋值与append和join之间存在如此大的性能差距。
所以我决定做一些更多的测试,最终发现是字典更新操作使程序变得异常缓慢。以下是脚本:
import time
LOOPS = 10000
WORD = 'ABC'*100
s1=time.time()
buf1 = []
for i in xrange(LOOPS):
buf1.append(WORD)
ss = ''.join(buf1)
s2=time.time()
buf2 = ''
for i in xrange(LOOPS):
buf2 += WORD
s3=time.time()
buf3 = {'1':''}
for i in xrange(LOOPS):
buf3['1'] += WORD
s4=time.time()
buf4 = {'1':[]}
for i in xrange(LOOPS):
buf4['1'].append(WORD)
buf4['1'] = ''.join(buf4['1'])
s5=time.time()
print s2-s1, s3-s2, s4-s3, s5-s4
在我的笔记本电脑(mac pro 2013中期,OS X 10.9.5,cpython 2.7.10)上,它的输出为:
0.00299620628357 0.00415587425232 3.49465799332 0.00231599807739
受juanpa.arrivillaga评论的启发,我对第二个循环进行了一些修改:
trivial_reference = []
buf2 = ''
for i in xrange(LOOPS):
buf2 += WORD
trivial_reference.append(buf2) # add a trivial reference to avoid optimization
更改后,现在第二个循环需要19秒才能完成。因此,正如juanpa.arrivillaga所说,这似乎只是一个优化问题。
+=
操作符来拼接字符串。 - Alex Fungtimeit
模块进行此类基准测试。 - bruno desthuilliersupdate
无关,而是可能涉及某种优化,如果只有一个对给定字符串的引用。将第三个循环更改为x = buf3.pop('1'); x+ = WORD; buf3['1'] = x
,结果几乎没有什么区别:0.00136399269104 0.00481796264648 0.00717210769653 0.00203800201416
。 - niemmibuf5 = ['']
和buf5 [0] + = WORD
,您会得到类似的缓慢响应。更新是缓慢的。 - muru