Clase de generador de Python

Ammar Ali 21 junio 2023
  1. Iteradores de Python
  2. Clase de generador de Python
Clase de generador de Python

Este tutorial discutirá el uso de la instrucción yield y la función next() para crear una clase generadora en Python.

Para comprender los generadores, primero debemos comprender los iteradores que se analizan a continuación.

Iteradores de Python

Los iteradores son objetos que se utilizan para acceder a los elementos de un contenedor uno por uno. Podemos usar la declaración for para recorrer los objetos contenedores para obtener los valores individualmente.

A continuación se muestra un código de ejemplo.

for element in [5, 6, 7]:
    print(element)

En el código de Python anterior, estamos recorriendo la lista de elementos e imprimiéndolos uno por uno. Entendamos lo que está sucediendo detrás de escena.

La declaración for llama a la función iter() en el objeto contenedor dado, y la función contiene un método __next__(), que accederá a cada elemento del objeto contenedor dado uno por uno.

El bucle terminará cuando la función __next__() genere una excepción StopIteration, y la excepción solo se generará cuando no haya más elementos presentes dentro del objeto contenedor dado.

Python también proporciona la función integrada next() que se puede utilizar para llamar a la función __next__(). Para usar la función next() en un objeto contenedor, tenemos que crear un objeto usando la función iter().

Por ejemplo, usemos una lista de números y llamemos a la función next() para obtener cada elemento de la lista uno por uno. Vea el código y la salida a continuación.

My_list = [5, 6, 7]
iter_object = iter(My_list)
print(next(iter_object))
print(next(iter_object))
print(next(iter_object))
print(next(iter_object))

Producción :

5
6
7
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-10-aa02bcda701b> in <module>
      4 print(next(iter_object))
      5 print(next(iter_object))
----> 6 print(next(iter_object))

StopIteration:

En el código anterior, llamamos a la función next() cuatro veces, devolviendo individualmente los tres elementos en el objeto de lista dado. Devolvió la excepción StopIteration cuando lo llamamos por cuarta vez porque no había más elementos presentes en el objeto de la lista.

También podemos llamar a la función next() mediante un bucle.

Usando la instrucción try-except, podemos evitar el error y usar el nombre de la excepción para terminar el ciclo. Por ejemplo, repitamos el código anterior usando un bucle y una instrucción try-except.

Vea el código y la salida a continuación.

My_list = [5, 6, 7]
iter_object = iter(My_list)

for i in range(len(My_list)):
    try:
        print(next(iter_object))
    except StopIteration:
        break

Producción :

5
6
7

En el código anterior, usamos el nombre de la excepción, StopIteration, para romper el ciclo. El iterador anterior devuelve valores uno por uno en una secuencia hacia adelante, pero también podemos definir nuestro propio iterador, que devolverá valores de acuerdo con nuestros requisitos.

Tenemos que definir tres funciones, __init__(), __iter__(), y __next__(), para agregar comportamiento de iterador a una clase. Por ejemplo, creemos una clase que devuelva los números de Fibonacci.

Ver el código a continuación

class Fibexample:
    def __init__(self):
        self.x, self.y = 0, 1

    def __iter__(self):
        return self

    def __next__(self):
        r_value = self.x
        self.x, self.y = self.y, self.x + self.y
        return r_value


fib = Fibexample()
for i in range(7):
    print(next(fib))

Producción :

0
1
1
2
3
5
8

La clase anterior devolverá un número de la serie de Fibonacci cada vez que se llame a la función next(). En el código anterior, llamamos a la función next() siete veces, devolviendo los primeros siete números de la serie de Fibonacci.

Clase de generador de Python

En Python, los generadores se utilizan para crear iteradores. Son las mismas que las funciones regulares; la única diferencia es usar la declaración de rendimiento en lugar de la declaración de retorno.

La instrucción yield() llamará a la función next() que devuelve un objeto iterador. Por ejemplo, creemos una función generadora que devuelva la misma serie de Fibonacci que el código anterior.

Vea el código y la salida a continuación.

def fibexample(data_input):
    x, y = 0, 1
    for index in range(data_input):
        z = x
        x, y = y, x + y
        yield z


obj = fibexample(7)
for i in obj:
    print(i)

Producción :

0
1
1
2
3
5
8

En el código anterior, la función fibexample() devolverá los números requeridos de la serie de Fibonacci en un objeto iterador. Podemos usar un ciclo para iterar a través del objeto para obtener cada valor presente en el objeto iterador.

El generador recuerda los valores de los datos y la última ejecución de la función next() y reanudará donde se quedó cuando se llame de nuevo a la función next().

El resultado de la función anterior es el mismo que obtuvimos en el ejemplo de los iteradores, pero el código anterior es relativamente corto en comparación con el código que usamos en el ejemplo de los iteradores. El beneficio de usar los generadores es que las funciones __iter__() y __next__() se crearán automáticamente, y los generadores también manejarán la excepción StopIteration.

Entonces, es fácil escribir iteradores usando los generadores porque crear iteradores usando generadores es como escribir una función simple usando la instrucción yield.

Autor: Ammar Ali
Ammar Ali avatar Ammar Ali avatar

Hello! I am Ammar Ali, a programmer here to learn from experience, people, and docs, and create interesting and useful programming content. I mostly create content about Python, Matlab, and Microcontrollers like Arduino and PIC.

LinkedIn Facebook

Artículo relacionado - Python Class