2 usuarios conectados

Funciones. Generadores en Python

Comparte esto

Ahora vamos a explorar los generadores en Python, una forma elegante y eficiente de crear iteradores. Los generadores son especialmente útiles para trabajar con secuencias de datos grandes o infinitas, ya que generan los elementos uno a la vez bajo demanda, en lugar de almacenarlos todos en memoria de una vez.

¿Qué son los Generadores?

Definición de Funciones Generadoras:

Para crear una función generadora, simplemente define una función normal pero utiliza la palabra clave yield una o más veces dentro de su cuerpo.

Python
 
def mi_generador():
    yield 1
    yield "dos"
    yield 3.0

# Crear un objeto generador llamando a la función
gen = mi_generador()

# Iterar sobre los valores generados
for valor in gen:
    print(valor)

Salida:

1
dos
3.0

¿Cómo funciona?

  1. Cuando llamas a mi_generador(), no se ejecuta el código de la función inmediatamente. En cambio, se crea un objeto generador.
  2. El bucle for (o una llamada a next() en el objeto generador) solicita el primer valor.
  3. La función mi_generador() se ejecuta hasta que encuentra la primera sentencia yield 1. El valor 1 se devuelve y la función se pausa, guardando su estado (incluyendo el punto de ejecución y los valores de las variables locales).
  4. En la siguiente iteración del bucle, se solicita el siguiente valor. La función mi_generador() se reanuda desde donde se quedó y continúa hasta la siguiente sentencia yield "dos". El valor "dos" se devuelve y la función se pausa de nuevo.
  5. Este proceso se repite hasta que la función llega al final (o encuentra una sentencia return sin valor), momento en el cual el generador lanza una excepción StopIteration, indicando que no hay más valores que producir. El bucle for maneja automáticamente esta excepción y termina.

Ejemplos de Uso de Generadores:

  1. Generador para producir una secuencia de números:

    Python
     
    def secuencia_hasta(n):
        i = 0
        while i < n:
            yield i
            i += 1
    
    for numero in secuencia_hasta(5):
        print(numero)
    

    Salida:

    0
    1
    2
    3
    4
    
  2. Generador para leer líneas de un archivo (eficiente para archivos grandes):

    Python
     
    def leer_lineas(nombre_archivo):
        with open(nombre_archivo, 'r') as archivo:
            for linea in archivo:
                yield linea.strip()  # Devuelve cada línea sin espacios en blanco al principio/final
    
    # Supongamos que 'mi_archivo.txt' contiene algunas líneas de texto
    for linea in leer_lineas('mi_archivo.txt'):
        print(f"Línea leída: {linea}")
    

    Este generador lee y devuelve cada línea del archivo una por una, sin cargar todo el archivo en memoria.

  3. Generador de números Fibonacci:

    Python
     
    def fibonacci_generador(n):
        a, b = 0, 1
        for _ in range(n):
            yield a
            a, b = b, a + b
    
    for num in fibonacci_generador(10):
        print(num)
    

    Salida:

    0
    1
    1
    2
    3
    5
    8
    13
    21
    34
    

Expresiones Generadoras:

Al igual que existen las comprensiones de lista, también existen las expresiones generadoras, que proporcionan una forma concisa de crear generadores anónimos utilizando una sintaxis similar a las comprensiones de lista, pero con paréntesis () en lugar de corchetes [].


Python
 
cuadrados = (x**2 for x in range(5))
print(cuadrados)  # <generator object <genexpr> at 0x...>

for cuadrado in cuadrados:
    print(cuadrado)

Salida:

<generator object <genexpr> at 0x...>
0
1
4
9
16

Las expresiones generadoras son aún más concisas que las funciones generadoras para casos simples.

Ventajas de los Generadores:

Los generadores son una herramienta poderosa en Python para el manejo eficiente de secuencias de datos, especialmente cuando la memoria es una preocupación o cuando se trabaja con flujos de datos continuos. ¿Te gustaría que pasemos al siguiente tema?