Los generadores extraen valores de una función, que se van a almacenar en objetos iterables. Esto quiere decir que estos objetos los vamos a poder recorrer con un bucle, iteradores o el método next.
Estos valores se almacenan de uno en uno y permanecen en un estado de espera
(pausa o suspensión de estado) hasta que se solicita el siguiente.
En una función en lugar de utilizar la instrucción return utilizamos la instrucción
yield.
En una función tradicional que construya una lista de valores, la instrucción
return nos devuelve todos los valores.
Pero la instrucción yield, sólo nos devuelve el primer valor y se mantiene a la
espera.
El control de flujo retorna a la llamada a la función y la llamar de nuevo a la
función nos retorna el segundo valor, por eso decimos que se generan objetos
iterables.
La diferencia estriba en que se nos devuelven los valores uno a uno, dentro de
un objeto iterable.
- Las ventajas:
- Es más eficiente que una función tradicional, menos consumo de memoria y
recursos.
- Para trabajar con listas de valores infinitos.
- La sintaxis es la misma que en una función
tradicional, en lugar de utilizar la instrucción return, utilizamos la instrucción
yield.
yield devuelve un valor individual y pausa la función.
yield
from itera sobre un iterable o generador, pasando sus valores al
llamador.
yield
from simplifica la iteración anidada y el manejo de generadores dentro
de generadores
yield:
Ideal
para crear iteradores que generan valores bajo demanda, ahorrando memoria al no
tener que almacenar todos los valores en una lista. Ejemplos: generar
secuencias infinitas, procesar archivos grandes línea por línea.
yield
from:
Útil para componer generadores a partir de otros generadores o
iterables, como unir secuencias, procesar datos de múltiples fuentes
def numeros(maxNum):
num=1
numLista=[]
while
num<=maxNum:
if
num%2==0:
numLista.append(num)
num=num+1
#print(numLista)
return
numLista
print(numeros(10))
# Lo mismo con un Generador.
def numeros(maxNum):
num=1
# Ya no necesito la lista.
while
num<=maxNum:
if
num%2==0:
#
No necesitamos añadir nada a la lista
#
Utilizamos Yield
yield
num
num=num+1
#print(numLista)
#
No necesitamos la instrucción Return.
#
return numLista
# Necesito fuera de la función
crear un variable que almacene el objeto iterable que devuelve la función.
resultado=numeros(10)
# Una vez que tenemos el objeto
iterable, lo recorremos con un bucle for o while.
for i in resultado:
print(i)
resultado2=numeros(10)
# El método next nos devuelve
valor a valor el contenido del objeto.
print(f"Valor 1º:
{next(resultado2)}")
print(f"Valor 2º:
{next(resultado2)}")
print(f"Valor 3º:
{next(resultado2)}")
# En este ejemplo podemos ver
como a cada llamada el control de flujo vuelve al objeto iterable.
# Entre una llamada y otra el
objeto generador está en pausa o estado de suspensión.
# Mientras que en una función
tradicional se genera la lista completa, en este caso no.
# Podemos generar valores
infinitos, sólo en el caso de que las llamadas sean infinitas.
#############
# Instrucción yield from, la utilizamos para simplificar código si utilizamos bucles anidados, un for dentro de un for.
# Similar a recorrer un array
bidimensional.
# Cuando colocamos un * delante del argumento indicamos que nos sabemos cuantos elementos recibirá.
# Y que estos elementos los
recibe en forma de TUPLA.
def Elementos(*elemento):
for i in elemento:
yield i
# Creo el elemento contenedor y paso los argumentos.
resultado=Elementos("Madrid",
"A Coruña", "Barcelona", "Ibiza")
# Utilizamo next para recorrer los valores.
print(f"Ciudad 1ª:
{next(resultado)}")
print(f"Ciudad 2ª:
{next(resultado)}")
print(f"Ciudad 3ª:
{next(resultado)}")
print("")
# Tenemos los elementos y
queremos acceder a los subelementos que son las letras.
def Elementos2(*elemento2):
for i in elemento2:
yield i
for a in i:
yield a
resultado2=Elementos2("Madrid",
"A Coruña", "Barcelona", "Ibiza")
print(f"Ciudad 1ª:
{next(resultado2)}")
print(f"Letra 1ª:
{next(resultado2)}")
print(f"Letra 2ª:
{next(resultado2)}")
print(f"Letra 3ª:
{next(resultado2)}")
print(f"Letra 3ª:
{next(resultado2)}")
print(f"Letra 3ª:
{next(resultado2)}")
print(f"Letra 3ª:
{next(resultado2)}")
print(f"Ciudad 2ª:
{next(resultado2)}")
print("")
def Elementos2(*elemento2):
for i in elemento2:
# Prescindimos del bucle anidado.
#for a in i:
yield from i
resultado2=Elementos2("Madrid",
"A Coruña", "Barcelona", "Ibiza")
print(f"Letra 1ª:
{next(resultado2)}")
print(f"Letra 2ª:
{next(resultado2)}")
print(f"Letra 3ª:
{next(resultado2)}")
print(f"Letra 3ª:
{next(resultado2)}")
print(f"Letra 3ª:
{next(resultado2)}")
print(f"Letra 3ª:
{next(resultado2)}")
print("")
def Sumarn(n):
v = num = 6
for i in range(n):
yield num
num += 1
print(f"Numero: {i+v}")
print(f"Suma Numeros:
{sum(Sumarn(5))}")
No hay comentarios:
Publicar un comentario
Gracias por vuestros aportes.