Mam funkcję generatora, jak poniżej:
def myfunct():
...
yield result
Zwykłym sposobem wywołania tej funkcji byłoby:
for r in myfunct():
dostuff(r)
Moje pytanie: czy istnieje sposób na uzyskanie tylko jednego elementu z generatora, kiedy tylko chcę? Na przykład chciałbym zrobić coś takiego:
while True:
...
if something:
my_element = pick_just_one_element(myfunct())
dostuff(my_element)
...
python
iterator
generator
python-2.x
Alexandros
źródło
źródło
next(gen, default)
można również użyć, aby uniknąćStopIteration
wyjątku. Na przykładnext(g, None)
dla generatora ciągów albo po zakończeniu iteracji albo powstanie ciąg, albo Żaden.next(g)
. To będzie wewnętrznie zadzwonićg.__next__()
, ale tak naprawdę nie trzeba się martwić o to, jak zwykle nie obchodzi, żelen(a)
wewnętrznie połączeńa.__len__()
.g.next()
jestg.__next__()
w py3k. Wbudowanenext(iterator)
jest już od Pythona 2.6 i jest tym, co powinno być używane w całym nowym kodzie Pythona, a implementacja wsteczna jest łatwa, jeśli potrzebujesz obsługiwać py <= 2.5.Do wybrania tylko jednego elementu generatora użyj
break
wfor
instrukcji lublist(itertools.islice(gen, 1))
Zgodnie z twoim przykładem (dosłownie) możesz zrobić coś takiego:
Jeśli chcesz „ dostać tylko jeden element z generatora [raz wygenerowanego] , kiedy tylko chcę ” (przypuszczam, że 50% to pierwotna intencja i najczęstsza intencja):
W ten sposób
generator.next()
można uniknąć jawnego użycia , a obsługa końca wejścia nie wymaga (tajemniczej)StopIteration
obsługi wyjątków lub dodatkowych porównań wartości domyślnych.else:
Zfor
sekcji oświadczenie jest potrzebne tylko wtedy, gdy chcesz zrobić coś specjalnego w przypadku wycofanych z generatora.Uwaga na
next()
/.next()
:W Python3
.next()
zmieniono nazwę tej metody.__next__()
na dobry powód: uważany za niski poziom (PEP 3114). Przed Pythonem 2.6 wbudowana funkcjanext()
nie istniała. Dyskutowano nawet o przejściunext()
dooperator
modułu (co byłoby mądre) ze względu na jego rzadką potrzebę i wątpliwą inflację wbudowanych nazw.Używanie
next()
bez domyślnych ustawień jest nadal bardzo niskim poziomem praktyki - rzucanie zagadkamiStopIteration
jak grom z jasnego nieba w normalnym kodzie aplikacji otwarcie. Korzystanienext()
z domyślnego wartownika - który najlepiej powinien być jedyną opcją dlanext()
bezpośredniegobuiltins
wejścia - jest ograniczone i często daje powód dziwnej nie pytonicznej logiki / zdolności odczytu.Konkluzja: Używanie next () powinno być bardzo rzadkie - podobnie jak korzystanie z funkcji
operator
modułu. Korzystaniefor x in iterator
,islice
,list(iterator)
oraz inne funkcje przyjmowania iterator bezproblemowo jest naturalnym sposobem korzystania iteratory na poziomie aplikacji - i dość zawsze możliwe.next()
jest niski poziom, dodatkowa koncepcja, nieoczywista - jak pokazuje pytanie tego wątku. Podczas gdy np. Używaniebreak
wfor
jest konwencjonalne.źródło
mySeq.head
?Nie sądzę, aby istniał wygodny sposób na uzyskanie dowolnej wartości z generatora. Generator zapewni następną () metodę przejścia przez siebie, ale pełna sekwencja nie jest tworzona natychmiast, aby zaoszczędzić pamięć. Na tym polega funkcjonalna różnica między generatorem a listą.
źródło
Dla tych, którzy przeglądają te odpowiedzi w celu uzyskania kompletnego przykładu dla Python3 ... cóż, proszę:
To daje:
źródło
Generator to funkcja tworząca iterator. Dlatego po utworzeniu instancji iteratora użyj next (), aby pobrać następny element z iteratora. Na przykład użyj funkcji next (), aby pobrać pierwszy element, a następnie użyj
for in
do przetworzenia pozostałych elementów:źródło
upewnij się, że złapałeś wyjątek zgłoszony po zajęciu ostatniego elementu
źródło
Uważam, że jedynym sposobem jest uzyskanie listy z iteratora, a następnie pobranie żądanego elementu z tej listy.
źródło
myfunct()
generuje dużą liczbę wartości), ponieważ można skorzystać z wbudowanej funkcjinext
, aby uzyskać kolejną wygenerowane wartości.