Jak wykonać pętlę przez generator


81

Jak jedna pętla może przejść przez generator? Myślałem o tym w ten sposób:

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

Czy jest bardziej pytoniczny sposób?


Sugerowałbym użycie break; niecontinue
Jon Clements

Właściwie zrobiłbym to w ten sposób w przypadku, gdy generator może rzucić wyjątek na element, ale nie chcesz przerywać iteracji.
robbrit

Odpowiedzi:


145

Po prostu

for x in gen:
    # whatever

da rade. Zauważ, że if genzawsze zwraca True.


6
Nie, if gennie zawsze wraca True. Jeśli PO za function_that_returns_a_generator()zwrotów None, genocenia się Falsew ifoświadczeniu.
drevicko

44
@drevicko: Zakładałem, że function_that_returns_a_generator()zwraca generator (odważne założenie, prawda?). Nonenie jest generatorem.
Sven Marnach

Ponieważ OP prosi o „pythonic sposób”, to odpowiedź wydaje się całkiem prawda, zważywszy, że Python opowiada EAFP ;-)
DerMike

17
for item in function_that_returns_a_generator(param1, param2):
    print item

Nie musisz martwić się testem, aby sprawdzić, czy funkcja zwraca coś, tak jakby nic nie zostało zwrócone, nie wejdziesz do pętli.


9

W przypadku, gdy nie potrzebujesz wyjścia generatora, ponieważ zależy Ci tylko na jego skutkach ubocznych, możesz użyć następującego jednoliniowca:

for _ in gen: pass

3
lub po prostulist(gen)
1919

7

Możesz po prostu zapętlić to:

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

Pamiętaj jednak, że pętlę można wykonać tylko raz. Następnym razem generator będzie pusty:

>>> for i in gen: print i
>>> 

4

Po prostu potraktuj to jak każdą inną iterowalną:

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

Zauważ, że if gen:zawsze będzie True, więc jest to fałszywy test


2

Jeśli chcesz ręcznie poruszać się po generatorze (tj. Ręcznie pracować z każdą pętlą), możesz zrobić coś takiego:

    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   

1
from pdb import set_trace # no () :)
Vlad K.

1

Pozostałe odpowiedzi są dobre w przypadku skomplikowanych scenariuszy. Jeśli chcesz po prostu przesłać elementy do listy:

x = list(generator)

(lub, jeśli chcesz po prostu uruchomić generator, aby coś zrobił, po prostu list(generator).

Do prostego przetwarzania wstępnego użyj wyrażeń listowych:

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

Lub gdy chcesz wykonać proste funkcje:

# didn't assign to variable b/c we don't care about what the print() function returns
[print(x) for x in gen]
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.