python - iteradores - ¿Cuál es la diferencia entre el aumento de StopIteration y una declaración de retorno en los generadores?
python funcion yield (3)
Tengo curiosidad acerca de la diferencia entre usar raise StopIteration
y una declaración de return
en los generadores.
Por ejemplo, ¿hay alguna diferencia entre estas dos funciones?
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
Supongo que la forma más "pirónica" de hacerlo es la segunda (por favor, corríjame si me equivoco), pero en la medida en que puedo ver ambas formas, generar una excepción StopIteration
.
A finales de 2014, la return
es correcta y el raise StopIteration
para terminar un generador se encuentra en un raise StopIteration
de depreciación. Ver PEP 479 para más detalles.
Resumen
Este PEP propone un cambio a los generadores: cuando
StopIteration
seStopIteration
dentro de un generador, se reemplaza conRuntimeError
. (Más precisamente, esto sucede cuando la excepción está a punto de desbordarse del marco de la pila del generador). Debido a que el cambio es incompatible con la__future__
, la función se introduce inicialmente con una declaración__future__
.Aceptación
Este PEP fue aceptado por el BDFL el 22 de noviembre ...
Razón fundamental
La interacción de los generadores y StopIteration es actualmente algo sorprendente y puede ocultar errores ocultos. Una excepción inesperada no debería dar como resultado un comportamiento alterado sutilmente, sino que debería causar un rastreo ruidoso y fácilmente depurado. Actualmente, StopIteration originado accidentalmente dentro de una función del generador se interpretará como el final de la iteración por la construcción de bucle que impulsa el generador.
...
Es cierto, son equivalentes, excepto que uno es legible mientras que el otro es oscuro. Esto se remonta a la primera versión de los generadores (PEP 255, en "Especificación: Devolución"), y las mejoras posteriores de (como, por ejemplo, las rutinarias) no cambian esto. El yield from
3.3 yield from
(PEP 380) extiende eso para return <expr>
como azúcar sintáctica para raise StopIteration(<expr>)
, pero eso no cambia el significado de return;
.
No hay necesidad de aumentar explícitamente StopIteration
ya que eso es lo que hace una declaración de return
StopIteration
para una función de generador, así que sí, son lo mismo. Pero no, solo usar return
es más pitónico.
De: http://docs.python.org/2/reference/simple_stmts.html#the-return-statement (válido para Python 3.2)
En una función de generador, la declaración de retorno no tiene permitido incluir una lista_expresión. En ese contexto, un retorno simple indica que el generador está listo y causará que se genere StopIteration.
O como señala @Bakuriu, la semántica de los generadores ha cambiado ligeramente para Python 3.3, por lo que lo siguiente es más apropiado:
En una función de generador, la declaración de retorno indica que el generador está listo y causará que se genere StopIteration. El valor devuelto (si existe) se usa como un argumento para construir StopIteration y se convierte en el atributo StopIteration.value.