¿Cómo funciona Yield en Python?

Para entender cómo funciona yield en Python, primero debemos entender que es un generador. Y antes de entender cómo funciona un generador, debes entender los iterables.

¡Empezemos entoces por los iterables!

Iterables

El iterable más sencillo de entender sería una lista: [0, 1, 2 ]. La lista la podemos leer elemento a elemento haciendo un sencillo for:

>>> my_list = [0, 1, 2]
>>> for i in my_list:
...    print(i)
0
1
2

my_list es un iterable, al igual, cuando usamos List comprehensions o comprensión de listas, creamos una lista que es un iterable.

>>> my_list = [x for x in range(3)]
>>> for i in my_list:
...    print(i)
0
1
2

Todos los elementos que podemos recorrer son un iterable.

¿Qué problemas presentan? Son fáciles de gestionar pero en caso de grandes cantidades de datos ocupan mucho espacio en memoria… y no siempre queremos usar todos los valores!

Y aquí es donde aparecen los generadores y nuestro querido yield.

Generadores

Los generadores son iterables, aunque algo diferente al que hemos visto más arriba. Sólo se pueden iterar una vez y no almacenan valores en memoria, los generan «en el momento» en el que son llamados.

>>> my_generator = (x for x in range(3))
>>> for i in my_generator:
...    print(i)
0
1
2

La única diferencia es que usamos ( ) en lugar de [ ]. NO podemos volver a ejecutar for i in my_generator: una segunda vez, el generador calcula el 0, luego olvida el valor y calcula el 1, y terminan calculando el 2 (uno a uno).

¿Y dónde entra en juego Yield?

Yield como return

Yield es la palabra reservada que se usa como return, a menos que la función devuelva otro generador.

En el caso anterior range(3) es un generador que genera una secuencia desde 0 hasta 3 (sin incluir este último), por eso no hemos visto la palabra yield por ninguna parte.

Pero si desgranáramos este generador, entonces quedaría algo así:

>>> def my_generator():
...    my_list = range(3)
...    for i in my_list:
...        yield i

Ahora realiza la misma función y vemos claramente la función del yield. Devuelve el valor y detiene la ejecución de esta pieza de código hasta la siguiente iteración.

>>> generador = my_generator()
>>> print(generador) # generador is an object!
<generator object create_generator at 0xb7555c34>

Debemos entender que el código no es ejecutado dónde es escrito, sino es almancenado en un objeto generador y es llamado una vez lo recorremos.

>>> for i in generador:
...     print(i)
0
1
2

¡Espero que este artículo te ayude optimizar tu código y ahorrar memoria!

Déjame en los comentarios dónde crees que sería útil utilizar en los generadores, ¡te leo en los comentarios!

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *