Lección 34 de 45 · Python intermedio

Iteradores y generadores

Hasta ahora has trabajado mucho con colecciones completas. Los generadores introducen otra idea: producir el siguiente valor solo cuando alguien lo necesita.

IteraciónEstado suspendidoNúcleo + ampliación
Índice · Lección 34/45
Piensa en una cinta transportadora, no en una caja llena

Una lista suele representar todos sus valores ya reunidos. Un generador se parece más a una cinta que entrega un elemento cada vez y conserva dónde se había quedado.

Esa diferencia importa cuando los datos son numerosos, llegan poco a poco o ni siquiera sabes de antemano cuántos habrá.

Evidencia de aprendizaje

Seguir el estado de un generador entre llamadas a next() y reconocer cuándo queda agotado.

El for ya sabe pedir valores a un iterador

No necesitas llamar a next() para aprovechar la idea
colores = iter(["rojo", "verde", "azul"])

for color in colores:
    print(color)

iter(...) obtiene un iterador. El for le pide sucesivamente el siguiente elemento hasta que ya no quedan más.

En el uso diario, rara vez necesitas manejar el final manualmente; el bucle lo hace por ti.

yield entrega un valor y congela temporalmente la función

La función continúa justo después del yield anterior
def cuenta_atras(desde):
    actual = desde
    while actual > 0:
        yield actual
        actual -= 1

for numero in cuenta_atras(3):
    print(numero)

Con return, una función termina. Con yield, entrega un valor, pausa y recuerda su estado. Cuando se solicita otro valor, continúa desde donde se detuvo.

Traza mental: para 3, el estado pasa por actual=3 → pausa → actual=2 → pausa → actual=1 → pausa → termina.

Consumir un generador significa avanzar por él

Un generador no es una lista reutilizable automáticamente. Si lo recorres hasta el final, ese mismo generador queda agotado.

La segunda vuelta ya no encuentra elementos
def dos_valores():
    yield "A"
    yield "B"

g = dos_valores()
print(list(g))
print(list(g))

Si necesitas recorrer los mismos datos varias veces y son pequeños, una lista puede ser más simple. Generador no significa «mejor»; significa «bajo demanda».

Mira cómo el generador se pausa

crearlotodavía no ejecuta el cuerpo
next()corre hasta el primer yield y se pausa
next()reanuda donde estaba y llega al siguiente yield
agotadootro next() produce StopIteration
Iterable

La fuente que puede proporcionar elementos.

Iterador

El objeto que recuerda por dónde va.

Un generador es una forma cómoda de crear un iterador mediante yield.

Haz que el generador entregue cuadrados. Después observa que tres llamadas a next() continúan desde el punto donde quedó pausado.

Salida esperada
1
4
9
generador.py
La salida aparecerá aquí.

Necesito una pista
  • No cambies el bucle; cambia el valor entregado por yield.
Ver una solución razonada
def cuadrados():
    for numero in [1, 2, 3]:
        yield numero * numero

g = cuadrados()
print(next(g))
print(next(g))
print(next(g))
¿Qué ocurriría con un cuarto next(g)?

El generador ya no tiene más valores y lanza StopIteration. Un for maneja ese agotamiento automáticamente.

El criterio no es «¿puedo usar yield?», sino «¿necesito todos los valores ya?»

  • Una lista reúne sus elementos; un generador puede producirlos cuando se solicitan.
  • yield pausa y conserva el estado de la función.
  • Un generador consumido no vuelve al principio por sí solo.
Puedes seguir cuando...

puedes explicar por qué un generador de un millón de elementos no necesita construir primero una lista de un millón de posiciones.