我认为探索使用genexp的好处会很有趣,所以这是我的看法 .
问题中的示例使用方括号来创建临时列表,因此等效于:
file.writelines( list( "%s\n" % item for item in list ) )
哪个不必要地构造了将要写出的所有行的临时列表,这可能会消耗大量内存,具体取决于列表的大小以及 str(item) 的输出有多详细 .
删除方括号(相当于删除上面的包装 list() 调用)将改为将临时generator传递给 file.writelines() :
file.writelines( "%s\n" % item for item in list )
此生成器将按需创建 item 对象的换行符(即,当它们被写出时) . 这很好,原因有两个:
内存开销很小,即使对于非常大的列表也是如此
如果 str(item) 很慢,则在处理每个项目时文件中都会有明显的进展
这可以避免内存问题,例如:
In [1]: import os
In [2]: f = file(os.devnull, "w")
In [3]: %timeit f.writelines( "%s\n" % item for item in xrange(2**20) )
1 loops, best of 3: 385 ms per loop
In [4]: %timeit f.writelines( ["%s\n" % item for item in xrange(2**20)] )
ERROR: Internal Python error in the inspect module.
Below is the traceback from this internal error.
Traceback (most recent call last):
...
MemoryError
(我通过使用 ulimit -v 102400 将Python的最大虚拟内存限制为~100MB来触发此错误) .
将内存使用放在一边,这种方法实际上并不比原始方法快:
In [4]: %timeit f.writelines( "%s\n" % item for item in xrange(2**20) )
1 loops, best of 3: 370 ms per loop
In [5]: %timeit f.writelines( ["%s\n" % item for item in xrange(2**20)] )
1 loops, best of 3: 360 ms per loop
(Linux上的Python 2.6.2)