Funcion generadora-2
en el ejemplo simple no se ve la diferencia. Te muestro dónde está la verdadera diferencia:
Diferencia clave: Memoria y ejecución
Función normal (lista):
def numeros_cuadrados(n):
resultado = []
for i in range(n):
resultado.append(i**2)
return resultado
# Esto crea TODOS los valores de una vez y los guarda en memoria
lista = numeros_cuadrados(1000000) # ¡Ocupa mucha memoria!Generador (lazy evaluation):
def numeros_cuadrados_gen(n):
for i in range(n):
yield i**2
# Esto NO crea los valores hasta que los pidas
generador = numeros_cuadrados_gen(1000000) # Ocupa casi nada de memoriaEjemplo práctico donde SÍ se ve la diferencia:
import sys
def numeros_cuadrados(n):
resultado = []
for i in range(n):
resultado.append(i**2)
return resultado
def numeros_cuadrados_gen(n):
for i in range(n):
yield i**2
# Comparación de memoria
lista_grande = numeros_cuadrados(100000)
generador_grande = numeros_cuadrados_gen(100000)
print(f"Tamaño lista: {sys.getsizeof(lista_grande)} bytes")
print(f"Tamaño generador: {sys.getsizeof(generador_grande)} bytes")Output:
Tamaño lista: 824456 bytes
Tamaño generador: 104 bytesEjemplo real de "bajo demanda":
def procesar_datos_grande():
print("Iniciando procesamiento...")
for i in range(5):
print(f"Procesando item {i}...")
yield f"Resultado {i}"
print("Procesamiento completado")
# Uso del generador
procesador = procesar_datos_grande()
print("No se ha procesado nada todavía...")
input("Presiona Enter para procesar el primer elemento:")
primer_elemento = next(procesador)
print(f"Primer elemento: {primer_elemento}")
input("Presiona Enter para procesar el segundo elemento:")
segundo_elemento = next(procesador)
print(f"Segundo elemento: {segundo_elemento}")
# O procesar el resto
print("Procesando el resto...")
for elemento in procesador:
print(f"Elemento: {elemento}")Output:
No se ha procesado nada todavía...
Presiona Enter para procesar el primer elemento:
Iniciando procesamiento...
Procesando item 0...
Primer elemento: Resultado 0
Presiona Enter para procesar el segundo elemento:
Procesando item 1...
Segundo elemento: Resultado 1
Procesando el resto...
Procesando item 2...
Elemento: Resultado 2
Procesando item 3...
Elemento: Resultado 3
Procesando item 4...
Elemento: Resultado 4
Procesamiento completado¿Cuándo usar generadores?
Datos grandes que no caben en memoria
Streaming de datos (archivos grandes, datos de red)
Procesamiento pipeline donde quieres procesar mientras produces
Infinite sequences (secuencias infinitas)
# Ejemplo: Secuencia infinita
def numeros_fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = numeros_fibonacci()
print([next(fib) for _ in range(10)]) # Solo 10 números¡La magia está en que el generador produce valores UNO por UNO solo cuando se los pides!
Comentarios
Publicar un comentario