Bienvenidos sean a este post, hoy veremos como trabaja next.
Cuando usamos a next(generador) en realidad estamos usando el metodo generator.__next__(), un metodo no es otra cosa que una funcion dentro del objeto, y su proposito es devolver el elemento siguiente de la iteracion o emerger un StopIteration cuando se termino la iteracion y ya no hay mas elementos que devolver.
Python transforma automaticamente nuestras funciones generadoras en un objeto que es muy similar a un iterador, es decir que cuando llamamos a next(generador) este lo transforma en generator.__next__(), para entender este concepto vamos a volver el ejemplo de cuadrados del post anterior:
>>> def get_cuadrados_gen(n) :
... for x in range(n):
... yield x ** 2
...
>>>
Es exactamente lo mismo donde generamos los cuadrados de un rango de numeros limitados por el numero informado, volvamos a almacenar el resultado en una variable:
>>> cuadrados = get_cuadrados_gen(3)
Tal como hicimos antes almacenamos todo lo producido con yield, nuestro siguiente paso sera probar devuelta a la funcion next:
>>> print(next(cuadrados))
0
>>>
Ahora vamos a probarlo pero en lugar de llamarlo de esta forma vamos a usar el metodo directo del objeto:
>>> print(cuadrados.__next__())
1
>>>
Como pueden ver es lo que deciamos anteriormente dado que podemos usarlo directamente o por medio del metodo del objeto, ademas de este metodo disponemos de tres metodos mas:
- send, nos permite enviar un valor de vuelta al objeto generador
- throw, se utiliza para emerger una excepcion con el generador
- close, cierra al generador
Vamos a crear un ejemplo donde aplicaremos varios conceptos nuevos:
>>> def contador(inicio=0) :
... n = inicio
... while True:
... yield n
... n += 1
...
>>>
Este es un contador iniciara un valor sin necesidad de informarla, nuestro siguiente paso sera iniciar un nombre con este valor, luego tenemos un bucle infinito porque al ser siempre True no terminara nunca, en este caso tenemos un yield de la variable antes iniciada y luego la incrementaremos en 1, esto lo hara por cada vuelta, veamos como trabaja:
>>> c = contador()
>>> print(next(c))
0
>>> print(next(c))
1
>>> print(next(c))
2
>>>
Primero almacenamos el resultado en un nombre llamado c, luego utilizamos varios next para poder ver como nos va mostrando cada uno de los valores que incrementamos, esto lo podemos hacer infinitamente pero ahora tomemos este codigo y hagamos la siguiente modificacion:
>>> def contador(inicio=0) :
... n = inicio
... while not detener :
... yield n
... n += 1
...
>>>
Es exactamente igual al anterior pero para este caso modificamos el while donde le decimos que mientras el valor de detener sea distinto de True haga el bucle, es un bucle infinito pero tenemos una condicion que puede detenerlo, nuestro siguiente paso sera:
>>> detener = False
>>> c = contador()
>>>
Primero definimos a detener con el valor de False, esto para el bucle anterior, luego definimos una variable con todos los valores de la funcion, con esto podemos probarlo pero lo haremos mediante el siguiente video
Como podemos ver en el video, el programa se sigue comportando como siempre mientras detener sea igual a False de lo contrario si lo establecemos como True al usar next nos devuelve un StopIteration, volvamos al ejemplo y modifiquemos la funcion de la siguiente forma:
>>> def contador(inicio=0) :
... n = inicio
... while True:
... resultado = yield n
... print(type(resultado), resultado)
... if resultado == 'Q':
... break
... n += 1
...
>>>
En este caso volvemos a modificar el while para que sea infinito, en este caso almacenaremos en resultado al valor producido por yield, lo siguiente sera mostrar el tipo almacenado en resultado junto al valor que posea, lo siguiente es un condicional donde verifica si resultado es igual a Q, en caso de ser verdadero usara a break para salir es decir que sera nuestra salida del iterador, por ultimo mientras no se cumpla la condicion seguiremos incrementando a n, con todo esto realizado vamos a probarlo mediante el siguiente video
Una vez ejecutado la primera vez nos devolvera solamente el valor de n porque no existe ningun valor en resultado pero en el segundo caso nos muestra el tipo, None porque es el tipo que devuelve yield, seguido del valor, en un momento pasamos por medio de send el valor Guauuuu el cual nos devuelve el tipo y el dato que pasamos pero luego veremos el valor siguiente del iterador y si lo seguimos usando veremos siempre esto hasta que pasamos la letra Q y ahi nos devuelve la excepcion StopIteration por el condicional antes comentado, no se ve muy facil de entender pero mas adelante y con practica comprenderemos mejor este tema.
En resumen, hoy hemos visto a next, hemos visto como realmente trabaja, como nos permite manejar la informacion, los otros metodos que tenemos disponibles, como podemos interrumpir un proceso y como podemos usar el send para enviar informacion entre los valores procesados por yield, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.00
