2013-01-06 7 views
21

Sono curioso della differenza tra l'utilizzo di raise StopIteration e una dichiarazione return nei generatori.Qual è la differenza tra sollevare StopIteration e un'istruzione return nei generatori?

Ad esempio, c'è qualche differenza tra queste due funzioni?

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 

sto cercando di indovinare il modo più "divinatorio" per farlo è il secondo modo (per favore correggetemi se sbaglio), ma per quanto posso vedere entrambi i modi sollevare un'eccezione StopIteration.

+2

esplicita o implicita ('l'estremità') 'return' è il modo intendeva chiudere un generatore. Se si accetta PEP 479, la versione 'raise StopIteration' alla fine non funzionerà come ora. –

risposta

28

Non è necessario aumentare in modo esplicito StopIteration poiché è una semplice dichiarazione return per una funzione di generatore, quindi sì, sono gli stessi. Ma no, solo usando return è più Pythonic.

Da: http://docs.python.org/2/reference/simple_stmts.html#the-return-statement (valido per Python 3,2)

In una funzione generatore, la dichiarazione di ritorno non è permesso di includere un expression_list. In quel contesto, un semplice ritorno indica che il generatore è stato fatto e causerà l'aumento di StopIteration.

O come @Bakuriu sottolinea - la semantica di generatori sono cambiate un po 'per Python 3.3, in modo che il seguente è più appropriato:

In una funzione generatore, l'istruzione return indica che il generatore è fatto e causerà l'arresto di StopIteration. Il valore restituito (se presente) viene utilizzato come argomento per costruire StopIteration e diventa l'attributo StopIteration.value.

+3

In python3 il ritorno può avere un argomento lista-espressioni: http://docs.python.org/3.3/reference/simple_stmts.html#the-return-statement – Bakuriu

3

Questo è vero, sono equivalenti tranne che uno è leggibile mentre l'altro è oscuro. Questo risale alla primissima versione di generatori (PEP 255, sotto "Specifica: Ritorno"), e i successivi miglioramenti (come le coroutine) non cambiano questo. Lo standard 3.3, yield from (PEP 380) lo estende a return <expr> come zucchero sintattico per raise StopIteration(<expr>), ma ciò non modifica il significato di return;.

12

A partire dalla fine del 2014 return è corretto e raise StopIteration per terminare un generatore è su un programma di ammortamento. Vedi PEP 479 per i dettagli completi.

astratta

Questa PEP propone una modifica ai generatori: quando StopIteration viene sollevato all'interno di un generatore, esso viene sostituito con RuntimeError. (Più precisamente, ciò accade quando l'eccezione sta per uscire dal frame dello stack del generatore.) Poiché la modifica è incompatibile con le versioni precedenti, la funzionalità viene inizialmente introdotta utilizzando un'istruzione __future__.

Accettazione

Questa PEP è stata accettata dal BDFL il 22 novembre ...

Razionale

L'interazione di generatori e StopIteration è attualmente un po 'sorprendente, e possono nascondere insetti oscuri.Un'eccezione imprevista non dovrebbe comportare un comportamento leggermente alterato, ma dovrebbe causare un traceback rumoroso e facilmente debug. Al momento, StopIteration generato accidentalmente all'interno di una funzione del generatore verrà interpretato come la fine dell'iterazione dal costrutto del loop che guida il generatore.

...

Problemi correlati