Как пройти через генератор

81

Как можно пройти через генератор? Я думал об этом так:

gen = function_that_returns_a_generator(param1, param2)
if gen: # in case the generator is null
    while True:
        try:
            print gen.next()
        except StopIteration:
            break

Есть ли более питонический способ?

iTayb
источник
Я бы предложил использовать break; нетcontinue
Джон Клементс
На самом деле я бы сделал это в том случае, если генератор может вызвать исключение для элемента, но вы не хотите останавливать итерацию.
robbrit

Ответы:

145

Просто

for x in gen:
    # whatever

сделает свое дело. Обратите внимание, что if genвсегда возвращается True.

Свен Марнах
источник
6
Нет, if genне всегда возвращается True. Если операция function_that_returns_a_generator()возвращается None, в операторе genоценивается Falseкак if.
drevicko
44
@drevicko: Я предполагал, что function_that_returns_a_generator()возвращает генератор (смелое предположение, не так ли?). Noneне генератор.
Sven Marnach
Поскольку OP запрашивает «питонический путь», этот ответ кажется вполне законным, учитывая, что Python поддерживает EAFP ;-)
DerMike
17
for item in function_that_returns_a_generator(param1, param2):
    print item

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

Кристиан Уиттс
источник
9

Если вам не нужен вывод генератора, потому что вы заботитесь только о его побочных эффектах, вы можете использовать следующую однострочную строку:

for _ in gen: pass
ммдж
источник
3
или простоlist(gen)
aiven 01
7

Вы можете просто пропустить его:

>>> gen = (i for i in range(1, 4))
>>> for i in gen: print i
1
2
3

Но имейте в виду, что цикл можно выполнить только один раз. В следующий раз генератор будет пуст:

>>> for i in gen: print i
>>> 
Войцех Калуски
источник
4

Просто относитесь к нему как к любому другому итерируемому:

for val in function_that_returns_a_generator(p1, p2):
    print val

Обратите внимание, что if gen:всегда будет True, поэтому это ложный тест.

Джон Клементс
источник
2

Если вы хотите вручную перемещаться по генератору (т. Е. Работать с каждым циклом вручную), вы можете сделать что-то вроде этого:

    from pdb import set_trace

    for x in gen:
        set_trace()
        #do whatever you want with x at the command prompt
        #use pdb commands to step through each loop of the generator e.g., >>c #continue   
Rysqui
источник
1
from pdb import set_trace # no () :)
Влад К.
1

Другие ответы подходят для сложных сценариев. Если вы просто хотите передать элементы в список:

x = list(generator)

(или, если вы просто хотите запустить генератор для выполнения каких-либо действий, просто list(generator) .

Для простой предварительной обработки используйте списки:

x = [tup[0] for tup in generator]

Или когда вы хотите выполнить простые функции:

# didn't assign to variable b/c we don't care about what the print() function returns
[print(x) for x in gen]
крипдик
источник