Каковы преимущества «доходности товара» и возврата товара (предметов)? - PullRequest
6 голосов
/ 03 июня 2011

В приведенных ниже примерах resp.results является итератором.

Версия 1:

items = []
for result in resp.results:
     item = process(result)
     items.append(item)
return iter(items)

Версия 2:

for result in resp.results:
     yield process(result)

Возвращает iter (элементы)в версии 1 лучше / хуже с точки зрения производительности / экономии памяти, чем просто возвращать предметы?

В «Кулинарной книге Python» Алекс говорит, что явный iter () «более гибок, но используется реже», но каковы плюсы / минусы возвращения iter (элементов) по сравнению с yield в версии 2?

Кроме того, каковы наилучшие способы юнит-тестирования итератора и / или выхода?- вы не можете сделать len (результаты), чтобы проверить размер списка?

Ответы [ 5 ]

4 голосов
/ 03 июня 2011

Легко превратить итератор или генератор обратно в список, если вам это нужно:

results = [item for item in iterator]

Или, как любезно указано в комментариях, еще более простой метод:

results = list(iterator)
4 голосов
/ 03 июня 2011

Первое приводит к тому, что все результаты вычисляются и сохраняются, в то время как второе является ленивой нагрузкой, в результате чего результаты вычисляются только по запросу. То есть один будет хранить и создавать список из N элементов, а другой будет хранить и создавать 0 элементов до тех пор, пока вы не начнете перебирать их.

Лучший способ думать об этом - использовать ifilter (из itertools ), в котором вы делаете то же самое, что и yield, за исключением того, что вы генерируете итератор вместо генератора:

 ifilter(process, resp.results)

Я обнаружил, что итераторы, как правило, выполняются быстрее, чем генераторы в серии 2.x, но я не могу проверить какую-либо экономию в серии 3.x.

3 голосов
/ 03 июня 2011

Когда вы обрабатываете очень большой список, то yield item лучше, так как он не занимает много памяти.

Смотрите отличную статью в генераторе http://www.dabeaz.com/generators/Generators.pdf

2 голосов
/ 04 июня 2011

Вы можете создавать бесконечные итераторы, но не бесконечные списки:

def fibGen():
    f0, f1 = 0, 1
    while True:
        yield f0
        f0, f1 = f1, f0+f1
1 голос
/ 03 июня 2011

Преимущества и предыдущего фрагмента в том, что все результаты вычисляются заранее.Это полезно, если время между извлечением каждого элемента имеет решающее значение, но не подходит, если итерация бесконечна или если пространство является проблемой.

...