Generadores
Son un tipo especial de itreador que genera datos mediante funciones, utilizando la palabra clave yield para devolver valores uno por uno (generación de datos "perezosa").
Ventajas
- Ahorro de memoria
- Escritura más concisa y clara en comparación con los iteradores tradicionales
Generadores vs Funciones Convencionales
- Funciones convencionales: Utilizan return para devolver un valor y finalizar la función
- Generadores: Utilizan yield para pausar la función, devolver un valor y recordar el estado de ejecución para la siguiente llamada
Uso
- Uso básico
def secuencia_hasta(maximo):
numero = 1
while numero <= maximo:
yield numero # Devuelve el número actual y pausa la ejecución
numero += 1
# Utilizando el generador
secuencia = secuencia_hasta(5)
# Obteniendo valores del generador
print(next(secuencia)) # Salida 1
print(next(secuencia)) # Salida 2
print(next(secuencia)) # Salida 3
print(next(secuencia)) # Salida 4
print(next(secuencia)) # Salida 5
El código anterior equivale al mecanismo interno de los bucles for...in... en python
def secuencia_hasta(maximo):
numero = 1
while numero <= maximo:
yield numero # Devuelve el número actual y pausa la ejecución
numero += 1
for valor in secuencia_hasta(5):
print(valor)
Para entendre el funcionamiento interno de los bucles for...in..., continúe leyendo
- Expresiones generadoras
# Expresión generadora
cuadrados = (x * x for x in range(5))
# Obteniendo valores del generador
print(next(cuadrados)) # Salida 0
print(next(cuadrados)) # Salida 1
print(next(cuadrados)) # Salida 4
print(next(cuadrados)) # Salida 9
print(next(cuadrados)) # Salida 16
Iteradores
Son objetos que permiten acceder a elementos de contenedores (como listas, tuplas, diccionarios, etc.) y devolver elementos uno por uno durante el proceso de recorrido.
Componentes
- Método iter: Devuelve el propio iterador. Este método hace que un objeto sea iterable (por ejemplo, listas o diccionarios pueden ser recorridos con un bucle for). Cuando se llama a la función iter() en un objeto, Python automáticamente invoca su método iter
- Método next: Devuelve el siguiente elemento del contenedor. Si no hay más elementos para devolver, el método next lanza una excepción StopIteration, indicando que la iteración ha finalizado
Uso simple
# Una lista de números
numeros = [10, 20, 30, 40, 50]
# Obteniendo el iterador
iterador = iter(numeros)
# Utilizando el iterador para obtener elementos uno por uno
print(next(iterador)) # Salida 10
print(next(iterador)) # Salida 20
print(next(iterador)) # Salida 30
Iterador personalizado
class ContadorRegresivo:
def __init__(self, inicio):
self.inicio = inicio
def __iter__(self):
return self
def __next__(self):
if self.inicio <= 0:
raise StopIteration # Fin de la iteración
actual = self.inicio
self.inicio -= 1
return actual
# Creando un objeto ContadorRegresivo e iterando
contador = ContadorRegresivo(5)
for num in contador:
print(num)
# Salida
5
4
3
2
1