В целом не используйте генератор, когда Вы должны будете перечислить операции, как len (), инвертированный (), и так далее.
могут также быть времена, когда Вы не хотите отложенные вычисления (например, сделать все вычисление впереди, таким образом, можно выпустить ресурс). В этом случае выражение списка могло бы быть лучше.
Профиль, Профиль, Профиль.
Профилирование Вашего кода является единственным способом знать, имеет ли то, что Вы делаете, какой-либо эффект вообще.
Большинство использований xrange, генераторов, и т.д. свыше статического размера, небольших наборов данных. Только, когда Вы добираетесь до больших наборов данных, это действительно имеет значение. диапазон () по сравнению с xrange () является главным образом просто вопросом того, чтобы заставлять код посмотреть крошечное, немного более ужасное, и не потеря чего-либо и возможно получение чего-то.
Профиль, Профиль, Профиль.
Вы никогда не должны одобрять zip
[более чем 1 110] izip
, range
[более чем 113] или понимания списка по пониманиям генератора. В Python 3.0 range
имеет xrange
- как семантика, и zip
имеет izip
- как семантика.
понимания Списка на самом деле более ясны как list(frob(x) for x in foo)
в течение тех времен, Вам нужен фактический список.
Как Вы упоминаете, "Это особенно имеет смысл для больших наборов данных", я думаю, что это отвечает на Ваш вопрос.
, Если Ваш не врезание в какие-либо стены, мудрые производительностью, можно все еще придерживаться списков и стандартных функций. Тогда, когда Вы сталкиваетесь с проблемами с производительностью, переключаются.
, Как упомянуто @u0b34a0f6ae в комментариях, однако, с помощью генераторов в запуске может облегчить для Вас масштабироваться к большим наборам данных.
Относительно производительности: при использовании психо, списки могут быть вполне немного быстрее, чем генераторы. В примере ниже, списки почти на 50% быстрее при использовании psyco.full ()
import psyco
import time
import cStringIO
def time_func(func):
"""The amount of time it requires func to run"""
start = time.clock()
func()
return time.clock() - start
def fizzbuzz(num):
"""That algorithm we all know and love"""
if not num % 3 and not num % 5:
return "%d fizz buzz" % num
elif not num % 3:
return "%d fizz" % num
elif not num % 5:
return "%d buzz" % num
return None
def with_list(num):
"""Try getting fizzbuzz with a list comprehension and range"""
out = cStringIO.StringIO()
for fibby in [fizzbuzz(x) for x in range(1, num) if fizzbuzz(x)]:
print >> out, fibby
return out.getvalue()
def with_genx(num):
"""Try getting fizzbuzz with generator expression and xrange"""
out = cStringIO.StringIO()
for fibby in (fizzbuzz(x) for x in xrange(1, num) if fizzbuzz(x)):
print >> out, fibby
return out.getvalue()
def main():
"""
Test speed of generator expressions versus list comprehensions,
with and without psyco.
"""
#our variables
nums = [10000, 100000]
funcs = [with_list, with_genx]
# try without psyco 1st
print "without psyco"
for num in nums:
print " number:", num
for func in funcs:
print func.__name__, time_func(lambda : func(num)), "seconds"
print
# now with psyco
print "with psyco"
psyco.full()
for num in nums:
print " number:", num
for func in funcs:
print func.__name__, time_func(lambda : func(num)), "seconds"
print
if __name__ == "__main__":
main()
Результаты:
without psyco
number: 10000
with_list 0.0519102208309 seconds
with_genx 0.0535933367509 seconds
number: 100000
with_list 0.542204280744 seconds
with_genx 0.557837353115 seconds
with psyco
number: 10000
with_list 0.0286369007033 seconds
with_genx 0.0513424889137 seconds
number: 100000
with_list 0.335414877839 seconds
with_genx 0.580363490491 seconds
Насколько производительность затронута, я не могу думать ни о каких временах, что Вы хотели бы использовать список по генератору.
Я никогда не находил ситуацию, где генераторы препятствовали бы тому, что Вы пытаетесь сделать. Существует, однако, много экземпляров, где использование генераторов больше не помогало бы Вам, чем не использование их.
, Например:
sorted(xrange(5))
не предлагает улучшения:
sorted(range(5))
Необходимо предпочесть понимания списка, если необходимо иметь в наличии значения для чего-то еще позже, и размер набора не является слишком большим.
, Например: Вы создаете список, который Вы циклично выполните более чем несколько раз позже в Вашей программе.
В некоторой степени можно думать о генераторах как о замене для повторения (циклы) по сравнению с пониманиями списка как тип инициализации структуры данных. Если Вы хотите сохранить структуру данных, тогда используют понимания списка.