Python:使用列表推导替代循环以提升性能

2 投票
2 回答
3365 浏览
提问于 2025-04-17 15:30

我有一个来自字典的类型(示例)

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 作为循环变量;在很多字体中,li 很容易搞混。

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() 的版本快。使用列表推导式虽然会创建不必要的列表,但也还不错,只是速度还是比普通的循环慢。

撰写回答