Iterators en Python: funcionalidad y uso de un vistazo

Los iteradores de Python son objetos Python con un conjunto contable de elementos que implementan el protocolo iterador formado por las funciones iter() y next().

¿Qué son exactamente los iterators en Python?

Los iterators de Python son principalmente una forma especial de objetos de Python. Se caracterizan por ser un conjunto de elementos contables. Así, puedes contar los elementos de un iterador e iterar sobre todos los elementos de un iterator de Python.

Consejo

Python es un excelente lenguaje de programación para proyectos web. Deploy Now te ayuda con la implementación automática y la construcción de tu proyecto a través de GitHub, para que siempre tengas una visión completa.

Iterators vs. Iterables

Los iterators en Python no deben confundirse con los Python iterables. Sin embargo, los iterators y los iterables están estrechamente relacionados. Los distintos iterables como la lista Python se caracterizan por tener un método iter() y por tanto permiten iterar a través de ellos. Como regla general, todo lo que está a la derecha de la cabecera del bucle cuando abres un bucle for es un iterable.

l = [1, 2, 3]
for x in l:
	print(x)
Python

Como puedes ver, la lista almacenada en la variable “l” aparece en la llamada al bucle for en Python a la derecha de la cabecera del bucle después de la palabra clave “in” y es por tanto un iterable.

Puedes derivar un iterator en Python de un iterable. Para aclarar esto y entender las diferencias, un ejemplo de código puede ayudarte:

string = "test"
objetoiterador = iter(string)
next(objetoiterador)
iter(objetoiterador)
Python

Primero, en el código, una Python string con el valor “test” se almacena en la variable llamada “string”. Las cadenas también entran en la categoría de iterables, porque puedes iterar a través de cada letra de la cadena.

El hecho de que puedas iterar a través de cadenas básicamente no significa otra cosa que una cadena también es compatible con la función iter(). Puedes verlo en la siguiente línea de código, donde se crea un iterator en Python llamando a la función iter junto con la cadena creada previamente. Esto devuelve un puntero a la cadena y lo almacena en la variable llamada “objetoiterador”. Así, el iterator en Python se encuentra en un estado. Es posible cambiar este estado llamando al método next() en el iterator en Python. Este método mueve el punto un carácter para que “objetoiterador” apunte a la primera letra de la cadena después de la llamada a la función.

La llamada a la función iter(), que toma el iterator en Python como parámetro, devuelve una referencia al mismo. Los iteradores en Python son, por tanto, autoiterables.

Iterators vs. Generators

También es importante distinguir los iterators de los Python generators. Aunque todo Python generator es también un iterador, no sucede lo mismo a la inversa. A diferencia de un generador, un iterador no se forma necesariamente con una función que contiene una expresión yield.

Consejo

Los Python iterators son un constructo de programación algo más avanzada que no cubren todos los tutoriales de Python. Si quieres aprender técnicas más avanzadas de Python, merece la pena que eches un vistazo a los siguientes artículos:

¿Para qué se utilizan los iterators en Python y por qué?

El uso principal de los iteradores es, por supuesto, la iteración misma. La gran ventaja de los iterators en Python es que funcionan según el principio de “Lazy Evaluation”. En otras palabras, esto significa que cada elemento de un iterator en Python puede ser procesado individualmente sin tener que cargar en memoria la estructura de datos en su totalidad. Este comportamiento es una ventaja de eficiencia, especialmente con grandes cantidades de datos, donde solo es necesario cargar un elemento cada vez.

Cómo crear iterators en Python

Crear tu propio iterator en Python no es difícil. Todo lo que tienes que hacer es añadir las funciones iter() y next() a un objeto Python. De esta forma puedes crear fácilmente un iterador que devuelva todos los números pares. Este ejemplo de código muestra cómo funciona exactamente:

class numerospares:
	def __iter__(self):
		self.x = 0
		return self
	def __next__(self):
		a = self.x
		self.x += 2
		return a
objetoprueba = numerospares()
iteradorprueba = iter(objetoprueba)
print(next(iteradorprueba))
print(next(iteradorprueba))
print(next(iteradorprueba))
print(next(iteradorprueba))
Python

Para crear un iterator en Python, primero se crea una clase, que aquí tiene el nombre “numerospares”. Dentro de la clase, las dos funciones iter() y next() se implementan cada una con el comportamiento deseado.

En nuestro caso, la función iter() simplemente devuelve una referencia al iterador que se supone que aloja la secuencia de enteros empezando por 0. La lógica de la iteración, es decir, que solo salga cada segundo y, por tanto, cada número par, está dentro de la función next().

Una vez definida la clase, se crea un objeto de la misma y se almacena en la variable llamada “objetoprueba”. El objeto se convierte en un iterator en Python llamando a la función iter(), como ya se ha mostrado en el ejemplo de código anterior. A continuación, se realizan cuatro llamadas a next(), cuyos resultados se muestran en pantalla. El resultado del bloque de código anterior sería el siguiente:

0
2
4
6

Limitar los iterators en Python

El iterador que itera sobre los números pares se ejecutaría hasta el infinito sin un límite al igual que el conjunto de números pares. Esto puede evitarse mediante una sentencia “StopIteration” junto con una sentencia if else de Python Por ejemplo, si deseas obtener todos los números pares hasta 100 inclusive en tu iterator en Python, debes adaptar el ejemplo de código anterior de la siguiente manera:

class numerospares:
	def __iter__(self):
		self.x = 0
		return self
	def __next__(self):
		if self.x <= 100:
			a = self.x
			self.x += 2
			return a	
		else:
			StopIteration
objetoprueba = numerospares()
iteradorprueba = iter(objetoprueba)
print(next(objetoprueba))
print(next(objetoprueba))
print(next(objetoprueba))
print(next(objetoprueba))
Python

Nada ha cambiado en el código excepto la implementación de la función next(). Se ha añadido una sentencia if else adicional que comprueba si el número actual es menor o igual que 100 e itera a través del conjunto de números pares solo bajo esta condición. Si el número supera el valor 100, se producirá un error a través de la llamada a StopIteration.