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):

python
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):

python
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 memoria

Ejemplo práctico donde SÍ se ve la diferencia:

python
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:

text
Tamaño lista: 824456 bytes
Tamaño generador: 104 bytes

Ejemplo real de "bajo demanda":

python
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:

text
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?

  1. Datos grandes que no caben en memoria

  2. Streaming de datos (archivos grandes, datos de red)

  3. Procesamiento pipeline donde quieres procesar mientras produces

  4. Infinite sequences (secuencias infinitas)

python
# 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

Entradas populares de este blog

¿Qué es un Closure?

Calculadora de edad

Funciones en Python: con y sin paréntesis