working with what used print generators generadores for are python generator

what - working with generators in python



Retorno en generador junto con rendimiento en Python 3.3 (2)

El valor de retorno no se ignora, pero los generadores solo arrojan valores, un return simplemente termina el generador, en este caso temprano. Avanzar el generador nunca alcanza la declaración de yield en ese caso.

Siempre que un iterador llegue al ''final'' de los valores para ceder, se debe StopIteration una StopIteration . Los generadores no son una excepción. A partir de Python 3.3, sin embargo, cualquier expresión de return convierte en el valor de la excepción:

>>> def gen(): ... return 3 ... yield 2 ... >>> try: ... next(gen()) ... except StopIteration as ex: ... e = ex ... >>> e StopIteration(3,) >>> e.value 3

Use la función next() para avanzar iteradores, en lugar de llamar .__next__() directamente:

print(next(x))

En Python 2 hubo un error cuando el retorno fue junto con el rendimiento en la definición de la función. Pero para este código en Python 3.3

def f(): return 3 yield 2 x = f() print(x.__next__())

no hay error de que el retorno se use en la función con rendimiento. Sin embargo, cuando se llama a la función __next__ se lanza la excepción StopIteration. ¿Por qué no solo se devuelve el valor 3 ? ¿Es este regreso ignorado de alguna manera?


Esta es una nueva característica en Python 3.3 (como notas de comentario, ni siquiera funciona en 3.2). Al igual que el return en un generador ha sido durante mucho tiempo equivalente a raise StopIteration() , return <something> en un generador ahora es equivalente a raise StopIteration(<something>) . Por esa razón, la excepción que está viendo debe imprimirse como StopIteration: 3 , y el valor es accesible a través del value del atributo en el objeto de excepción. Si el generador se delega para usar el yield from (también nuevo) yield from sintaxis, es el resultado. Ver PEP 380 para más detalles.

def f(): return 1 yield 2 def g(): x = yield from f() print(x) # g is still a generator so we need to iterate to run it: for _ in g(): pass

Esto imprime 1 , pero no 2 .