Python:使用List Comprehensions而不是循环来提​​高性能

时间:2013-02-11 15:28:24

标签: python performance optimization list-comprehension

我有字典中的类型(示例)

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 个答案:

答案 0 :(得分:9)

循环理解不一定加速循环。如果结果应该是一个列表,它们只会加速循环。列表推导比创建一个空列表并逐个追加它更快。

在您的情况下,您希望将项目写入文件,而不是创建新列表。然后浪费列表创建成本。

您不需要xrange()来电,只需循环l[1]。您也不需要.iteritems(),因为您忽略了键。请改用.itervalues()

for lst in Groups.itervalues():
    for p in lst:
        file_out.write(p)

我使用lst作为循环变量;很多字体l容易混淆i

答案 1 :(得分:4)

如果您想要更短的解决方案,请考虑将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()版本快。创建不需要的列表的列表理解也不错,但仍然比普通周期慢。