Durante mucho tiempo no supe que no se puede poner return delante de una declaración de rendimiento. Pero en realidad puedes:
def gen(): return (yield 42)que es similar a
def gen(): yield 42 return Y el único uso que se me ocurre es adjuntar el valor enviado a StopIteration : pep-0380
return expr en un generador hace que StopIteration(expr) se eleve al salir del generador.
def gen(): return (yield 42) g = gen() print(next(g)) # 42 try: g.send('AAAA') except StopIteration as e: print(e.value) # 'AAAA'Pero esto también se puede hacer usando una variable adicional, que es más explícita:
def gen(): a = yield 42 return a g = gen() print(next(g)) try: g.send('AAAA') except StopIteration as e: print(e.value) # 'AAAA' Entonces parece que el return (yield xxx) es simplemente un azúcar sintáctico. ¿Me estoy perdiendo de algo?
Dentro de un generador, las expresiones (rendimiento 42) arrojarán el valor 42, pero también devuelve un valor que es Ninguno, si usas next(generator) o un valor dado si usas generator.send(value) .
Entonces, como usted dice, podría usar un valor intermedio para obtener el mismo comportamiento, no porque esto sea azúcar sintáctico, sino porque las expresiones de rendimiento literalmente devuelven el valor que le envía.
Igual podrías hacer algo como
def my_generator(): return (yield (yield 42) + 10)Si llamamos a esto, usando la secuencia de llamadas:
g = my_generator() print(next(g)) try: print('first response:', g.send(1)) print('Second response:', g.send(22)) print('third response:', g.send(3)) except StopIteration as e: print('stopped at', e.value) Primero obtenemos la salida de 42, y el generador está esencialmente en pausa en un estado que podría describir como: return (yield <Input will go here> + 10) , si luego llamamos a g.send(1) obtenemos la salida 11 y el generador está ahora en el estado: return <Input will go here> , luego enviar g.send(22) arrojará un StopIteration(22) , debido a la forma en que se maneja el retorno en los generadores. Entonces nunca llegas al tercer envío debido a la excepción.
Espero que este ejemplo haga un poco más evidente cómo funciona el yield en los generadores y por qué la return (yield something) no es nada especial o exótico y funciona exactamente como lo esperarías.
En cuanto a la pregunta literal, ¿cuándo harías esto? Bueno, cuando quiera producir algo, y luego devolver una StopIteration haciendo eco de la entrada del usuario enviada al generador. Porque esto es literalmente lo que dice el código. Espero que tal comportamiento rara vez sea deseado.