2013-01-06 4 views
21

Jestem ciekawa różnicy między używaniem instrukcji raise StopIteration i return w generatorach.Jaka jest różnica między podniesieniem StopIteration a instrukcją return w generatorach?

Na przykład, czy istnieje jakaś różnica między tymi dwiema funkcjami?

def my_generator0(n): 
    for i in range(n): 
     yield i 
     if i >= 5: 
      return 

def my_generator1(n): 
    for i in range(n): 
     yield i 
     if i >= 5: 
      raise StopIteration 

Zgaduję bardziej „pythonic” sposobem na to jest drugi sposób (proszę mnie poprawić, jeśli się mylę), ale o ile widzę oba sposoby podniesienia StopIteration wyjątek.

+2

jawny lub niejawny ('off koniec') 'return' jest zamierzony sposób, aby zakończyć generator. Jeśli PEP 479 zostanie zaakceptowany, wersja "podnieś stoperowanie" ostatecznie nie będzie działać tak jak teraz. –

Odpowiedz

28

Nie ma potrzeby, aby jawnie podnosić StopIteration, ponieważ to jest to, co robią puste instrukcje return dla funkcji generatora - więc tak, są takie same. Ale nie, po prostu użycie return jest bardziej Pythoniczne.

z: http://docs.python.org/2/reference/simple_stmts.html#the-return-statement (ważne Python 3.2)

W funkcję generatora, rachunek powrotu nie może zawierać expression_list. W tym kontekście nieuzasadniony powrót wskazuje, że generator jest gotowy i spowoduje zatrzymanie.

Albo jak @Bakuriu zaznacza - semantyka generatorów zmieniły się nieznacznie dla Pythona 3.3, więc po to bardziej odpowiednie:

W funkcji generatora, instrukcja return wskazuje, że generator jest zrobione i spowoduje Przerwanie. Zwrócona wartość (jeśli występuje) jest używana jako argument do utworzenia StopIteration i staje się atrybutem StopIteration.value.

+3

W python3 return może mieć argument listy-wyrażeń: http://docs.python.org/3.3/reference/simple_stmts.html#the-return-statement – Bakuriu

3

To prawda, są one równoważne, z wyjątkiem tego, że można je odczytać, podczas gdy inne są niejasne. To pochodzi z pierwszej wersji generatorów (PEP 255, w części "Specyfikacja: Zwrot"), a kolejne ulepszenia (takie jak coroutines) nie zmieniają tego. 3.3's yield from (PEP 380) rozszerza to do return <expr> jako cukier syntaktyczny dla raise StopIteration(<expr>), ale to nie zmienia znaczenia return;.

12

Pod koniec 2014 r. return jest poprawny, a raise StopIteration na zakończenie generatora znajduje się w harmonogramie amortyzacji. Aby uzyskać szczegółowe informacje, patrz PEP 479.

Streszczenie

Ten PEP proponuje zmiany do generatorów: kiedy StopIteration jest podniesiony wewnątrz generatora, jest on zastępowany RuntimeError. (Dokładniej, dzieje się tak, gdy wyjątek ma zacząć bańkę z ramki stosu generatora.) Ponieważ zmiana jest niezgodna wstecz, funkcja jest początkowo wprowadzona za pomocą instrukcji __future__.

Akceptacja

PEP ta została zaakceptowana przez BDFL dniu 22 listopada ...

Uzasadnienie

Interakcja generatorów i StopIteration jest obecnie nieco zaskakujące i może ukryć niejasnych błędów.Nieoczekiwany wyjątek nie powinien powodować nieznacznie zmienionych zachowań, ale powinien powodować hałaśliwe i łatwe do debugowania śledzenie. Obecnie StopIteracja podniesiona przypadkowo w funkcji generatora zostanie zinterpretowana jako koniec iteracji przez konstrukcję pętli sterującą generatorem.

...

Powiązane problemy