Python:使用列表推导替代循环以提升性能
我有一个来自字典的类型(示例)
l =('1037_97',["a","b","c","d","e"])
我想保存一个文件(las格式),但是Liblas只能写入单个点。
for l in Groups.iteritems():
for p in xrange(len(l[1])):
file_out.write(l[1][p])
我正在尝试使用如果可能的话列表推导式,这样可以节省代码并加快循环的速度。
2 个回答
10
循环推导式并不一定能让循环更快。只有当你最终想要的结果是一个列表时,它才会加速循环。使用列表推导式比先创建一个空列表然后一个一个地添加元素要快。
在你的情况中,你是想把项目写入文件,而不是创建一个新列表。所以创建列表的时间就浪费掉了。
你其实不需要使用 xrange()
,只需直接遍历 l[1]
。而且你也不需要 .iteritems()
,因为你并不关心键。可以用 .itervalues()
来代替:
for lst in Groups.itervalues():
for p in lst:
file_out.write(p)
我用了 lst
作为循环变量;在很多字体中,l
和 i
很容易搞混。
5
如果你想要一个更简短的解决方案,可以考虑在内层循环中使用 map()
,甚至可以在外层循环中也用它。不过,这样做可能不会带来明显的性能提升。不过,使用 for p in l[1]:
可能还是比用 xrange
的方式要快。下面这个例子应该能在一行内完成你想要的操作:
map(lambda g: map(file_out.write, g), groups.itervalues())
现在我们来比较不同实现的性能。我在一些测试数据上测量了时间:
import timeit
groups = dict(('1037_%d' % i, ["a","b","c","d","e"]) for i in xrange(100))
class FOut(object):
def write(self, v):
#print v
pass
file_out = FOut()
def using_map():
map(lambda g: map(file_out.write, g), groups.itervalues())
def initial_version():
for l in groups.iteritems():
for p in xrange(len(l[1])):
file_out.write(l[1][p])
def seq_iteration():
for l in groups.iteritems():
for p in l[1]:
file_out.write(p)
def seq_iteration_values():
for l in groups.itervalues():
for p in l:
file_out.write(p)
def list_compr():
[[file_out.write(v) for v in g] for g in groups.itervalues()]
tests = ('initial_version', 'using_map', 'seq_iteration', 'list_compr', 'seq_iteration_values')
for test in tests:
print test, timeit.timeit('%s()'%test, 'from __main__ import %s'%test, number=10000)
结果是:
initial_version 0.862531900406
using_map 0.703296899796
seq_iteration 0.541372060776
list_compr 0.632550954819
seq_iteration_values 0.493131160736
从结果来看,你最开始的版本是最慢的,修正循环的方式能大大提升速度,map()
的版本虽然简短,但速度没有 itervalues()
的版本快。使用列表推导式虽然会创建不必要的列表,但也还不错,只是速度还是比普通的循环慢。