Я подумал, что было бы интересно изучить преимущества использования genexp, так что вот мое мнение.
Пример в вопросе использует квадратные скобки для создания временного списка, и поэтому эквивалентен:
file.writelines( list( "%s\n" % item for item in list ) )
Что создает ненужный временный список всех строк, которые будут записаны, это может занять значительные объемы памяти в зависимости от размера вашего списка и от того, насколько многословным является вывод str(item)
.
Снятие квадратных скобок (эквивалентное удалению вызова list()
выше) вместо этого передаст временный генератор в 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
(я вызвал эту ошибку, ограничив максимальную виртуальную память Python до ~ 100 МБ при ulimit -v 102400
).
Если перевести использование памяти в одну сторону, этот метод на самом деле не быстрее оригинального:
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
(Python 2.6.2 в Linux)