En la programación en Python, comprender y utilizar los iterables con eficacia es fundamental para una programación competente. Los iterables son objetos sobre los que puedes iterar o hacer un bucle. Permiten recorrer secuencialmente los elementos que contienen, lo que los convierte en una herramienta fundamental para acceder y manipular elementos de objetos o estructuras de datos.

Este artículo explora cómo utilizar correctamente los iterables de Python, centrándose en los tipos de datos iterables incorporados al lenguaje: listas, tuplas, diccionarios, cadenas y conjuntos. También explica cómo implementar tipos iterables personalizados y realizar operaciones avanzadas.

Cómo Recorrer Iterables en Python

En Python, puedes iterar a través de diversos tipos de iterables utilizando un bucle for. Esto te permite recorrer secuencias y realizar operaciones sobre elementos individuales dentro de listas, conjuntos y diccionarios.

La palabra clave for en Python se desvía de su utilidad en otros lenguajes orientados a objetos como Java. Los bucles de Python for funcionan más como métodos iteradores. Aquí tienes ejemplos para demostrar los bucles en iterables:

1. Bucle en una Lista

Las listas son colecciones ordenadas de elementos, lo que permite una iteración sencilla mediante un bucle for.

fruits_list = ["Apple", "Mango", "Peach", "Orange", "Banana"]

for fruit in fruits_list:
    print(fruit)

En el código anterior, fruit actúa como un iterador que el bucle utiliza para recorrer cada elemento de la lista mientras los imprime simultáneamente. El bucle termina tras evaluar el último elemento de la lista. El código anterior debería dar la siguiente salida:

Apple
Mango
Peach
Orange
Banana

2. Iterando a Través de una Tupla

Las tuplas son similares a las listas, pero inmutables. Puedes iterar a través de ellas igual que con las listas.

fruits_tuple = ("Apple", "Mango", "Peach", "Orange", "Banana")

for fruit in fruits_tuple:
	print(fruit)

En este ejemplo, el bucle for itera a través de la tupla y, en cada iteración, la variable fruit toma el valor del elemento actual de la tupla. El código debería dar el siguiente resultado:

Apple
Mango
Peach
Orange
Banana

3. Recorriendo Conjuntos con Bucles

Los conjuntos son colecciones desordenadas de elementos únicos. Puedes recorrerlas utilizando un bucle for.

fruits_set = {"Apple", "Mango", "Peach", "Orange", "Banana"}

for fruit in fruits_set:
	print(fruit)

En este ejemplo, el bucle for itera a través del conjunto. Sin embargo, como los conjuntos no están ordenados, el orden de iteración puede no coincidir con el orden en que se definieron los elementos en el conjunto. En cada iteración, la variable fruit toma el valor del elemento actual del conjunto. El código debe dar una salida similar a la siguiente (el orden puede variar):

Mango
Banana
Peach
Apple
Orange

4. Iterando a Través de Cadenas

Las cadenas son secuencias de caracteres que puedes recorrer carácter a carácter.

string = "Kinsta"

for char in string:
	print(char)

El código anterior itera a través de la cadena «Kinsta» e imprime cada carácter en una nueva línea. En cada iteración, la variable char toma el valor del carácter actual de la cadena. El código debería dar la siguiente salida:

K
i
n
s
t
a

5. Recorriendo un Diccionario

Utilizar el bucle for es similar para listas, conjuntos, tuplas y cadenas, pero es diferente para los diccionarios, ya que utilizan pares clave-valor para almacenar elementos. Los diccionarios presentan un caso único para el bucle, ya que puedes iterarlos utilizando distintos enfoques. Éstos son los distintos enfoques que puedes utilizar para recorrer un diccionario de Python:

  • Iterar a través de las claves:
    countries_capital = {
        "USA": "Washington D.C.",
        "Australia": "Canberra",
        "France": "Paris",
        "Egypt": "Cairo",
        "Japan": "Tokyo"
    }
    
    for country in countries_capital.keys():
        print(country)

    El código anterior define un diccionario llamado countries_capital, donde los nombres de los países son las claves, y sus respectivas capitales son los valores. El bucle for itera a través de las claves del diccionario countries_capital utilizando el método keys(). Este método devuelve un objeto vista que muestra una lista de las claves del diccionario, lo que facilita el bucle a través de todas las claves. En cada iteración, la variable country toma el valor de la clave actual. Este código debería dar la siguiente salida:

    USA
    Australia
    France
    Egypt
    Japan
  • Iterando a través de los valores:
    countries_capital = {
        "USA": "Washington D.C.",
        "Australia": "Canberra",
        "France": "Paris",
        "Egypt": "Cairo",
        "Japan": "Tokyo"
    }
    
    for capital in countries_capital.values():
        print(capital)

    En el código anterior, el for itera a través de los valores del diccionario countries_capital utilizando el método values(). Este método devuelve un objeto vista que muestra una lista de los valores del diccionario, facilitando la iteración a través de todos los valores. En cada iteración, la variable capital toma el valor del valor actual de la lista. Este código debería dar la siguiente salida:

    Washington D.C.
    Canberra
    Paris
    Cairo
    Tokyo
  • Iterando a través de pares clave-valor:
    countries_capital = {
        "USA": "Washington D.C.",
        "Australia": "Canberra",
        "France": "Paris",
        "Egypt": "Cairo",
        "Japan": "Tokyo"
    }
    
    for country, capital in countries_capital.items():
        print(country, ":", capital)

    El código anterior demuestra cómo iterar a través de las claves y los valores del diccionario countries_capital utilizando el método items(). El método items() devuelve un objeto vista que muestra una lista de tuplas clave-valor del diccionario. En el bucle for, cada iteración desempaqueta un par clave-valor del elemento actual de la lista. A las variables country y capital se les asigna la clave y el valor correspondientes, respectivamente. Este código debería dar el siguiente resultado:

    USA : Washington D.C.
    Australia : Canberra
    France : Paris
    Egypt : Cairo
    Japan : Tokyo

Iteración Avanzada con enumerate() en Python

Otra forma de iterar sobre iterables de Python devolviendo tanto el índice como el valor correspondiente de los elementos es mediante la función enumerate(). Mira este ejemplo:

fruits_list = ["Apple", "Mango", "Peach", "Orange", "Banana"]

for index, fruit in enumerate(fruits_list):
    print(fruit, index)

Este es el resultado:

Apple 0
Mango 1
Peach 2
Orange 3
Banana 4

La función enumerate también te permite especificar el índice inicial, además de 0, para la operación de iteración. Puedes modificar el ejemplo anterior como sigue:

fruits_list = ["Apple", "Mango", "Peach", "Orange", "Banana"]
for index, fruit in enumerate(fruits_list, start = 2):
    print(fruit, index)

Este es el resultado:

Apple 2
Mango 3
Peach 4
Orange 5
Banana 6

Observa que, aunque este ejemplo especifica el índice inicial de la enumeración, enumerate no aplica una indexación basada en cero a la iterable, como ocurre con las listas nativas. Simplemente añade el valor inicial al primer elemento de la lista hasta el último.

Cómo Implementar los Generadores de Python

Los generadores son iterables especiales de Python que te permiten construir objetos generadores sin crear explícitamente tipos incorporados como listas, conjuntos o diccionarios. Puedes utilizar generadores para producir valores sobre la marcha basándote en la lógica de generación.

Los generadores utilizan la sentencia yield para devolver los valores generados de uno en uno. Aquí tienes un ejemplo de iterables generadores:

def even_generator(n):
    counter = 0
    while counter <= n:
        if counter % 2 == 0:
            yield counter
        counter += 1

for num in even_generator(20):
    print(num)

El código proporcionado define una función even_generator que produce una secuencia de números pares desde 0 hasta un n especificado utilizando la sentencia yield. Utiliza un bucle para generar estos valores e itera a través del resultado utilizando el iterador num, asegurando la evaluación de todos los valores dentro del rango dado. Este código genera una lista de números pares desde 0 hasta 20, como se muestra a continuación:

0
2
4
6
8
10
12
14
16
18
20

Puedes conseguir aún más concisión cuando trabajes con expresiones generadoras. Por ejemplo, puedes diseñar una función generadora que también incorpore lógica de bucle:

cube = (num ** 3 for num in range(1, 6))
for c in cube:
    print(c)

Aquí, asignas la variable cube al resultado de una función que calcula el cubo de los valores comprendidos entre 1 y 6. A continuación, realiza un bucle a través de los valores dentro del intervalo especificado, mostrando el resultado del cálculo, uno tras otro. El resultado es el siguiente:

1
8
27
64
125

Cómo Construir Iterables Personalizados

Python te permite personalizar aún más las operaciones iterables utilizando iteradores. Los objetos iteradores implementan el protocolo iterador y contienen 2 métodos: __iter__() y __next__(). El método __iter__() devuelve un objeto iterador, mientras que __next__() devuelve el siguiente valor en un contenedor iterable. Aquí tienes un ejemplo de iteradores en Python:

even_list = [2, 4, 6, 8, 10]
my_iterator = iter(even_list)
print(next(my_iterator)) # Prints 2
print(next(my_iterator)) # Prints 4
print(next(my_iterator)) # Prints 6

En este ejemplo, utilizas el método iter() para crear un objeto iterador (my_iterator) a partir de la lista. Para acceder a cada uno de los elementos de la lista, envuelves el objeto iterador con el método next(). Como las listas son colecciones ordenadas, el iterador devuelve los elementos secuencialmente.

Los iteradores personalizados son ideales para operaciones que implican grandes conjuntos de datos que no puedes cargar en memoria simultáneamente. Como la memoria es cara y propensa a las limitaciones de espacio, puedes utilizar un iterador para procesar elementos de datos individualmente sin cargar todo el conjunto de datos en la memoria.

Funciones Iterables

Python utiliza funciones para recorrer, manipular e inspeccionar los elementos de una lista. Algunas funciones de lista comunes son:

  • sum — Devuelve la suma de un iterable dado, siempre que la colección sea de tipos numéricos (enteros, valores de coma flotante y números complejos)
  • any — Devuelve true si alguno de los elementos del iterable es verdadero. En caso contrario, devuelve false.
  • all — Devuelve true si todos los elementos del iterable son verdaderos. En caso contrario, devuelve false.
  • max — Devuelve el valor máximo de una colección iterable dada
  • min — Devuelve el valor mínimo de una colección iterable dada
  • len — Devuelve la longitud de un iterable dado
  • append — Añade un valor al final de una lista iterable

El siguiente ejemplo muestra estas funciones con una lista:

even_list = [2, 4, 6, 8, 10]

print(sum(even_list))
print(any(even_list))
print(max(even_list))
print(min(even_list))
even_list.append(14) # Add 14 to the end of the list
print(even_list)
even_list.insert(0, 0) # Insert 0 and specified index [0]
print(even_list)
print(all(even_list)) # Return true only if ALL elements in the list are true
print(len(even_list)) # Print the size of the list

Éste es el resultado:

30
True
10
2
[2, 4, 6, 8, 10, 14]
[0, 2, 4, 6, 8, 10, 14]
False
7

En el ejemplo anterior, la función append añade un único parámetro (14) al final de la lista. La función insert permite especificar el índice de inserción. Por lo tanto, even_list.insert(0, 0) inserta 0 en el índice [0].
La sentencia print(all(even_list)) devuelve false porque hay un valor 0 en la lista, interpretado como false. Por último, print(len(even_list)) devuelve la longitud del iterable.

Operaciones Avanzadas con Iterables

Python ofrece funciones avanzadas que favorecen la concisión en las operaciones con iterables. A continuación se enumeran algunas de ellas.

1. Comprensiones de lista

Las comprensiones de listas te permiten crear nuevas listas aplicando una función a cada elemento de las listas existentes. Aquí tienes un ejemplo:

my_numbers = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
even_number_list = [num for num in my_numbers if num%2 == 0]
print(even_number_list)

En este fragmento de código, se crea una lista llamada my_numbers con enteros de 11 a 20. El objetivo es generar una nueva lista, even_number_list, que contenga sólo enteros pares. Para conseguirlo, aplica una comprensión de lista que devuelva un entero de my_numbers sólo si ese entero es par. La sentencia if contiene la lógica que devuelve los números pares.

Este es el resultado:

[12, 14, 16, 18, 20]

2. Zip

La función zip() de Python combina múltiples iterables en tuplas. Las tuplas almacenan múltiples valores en una variable y son inmutables. A continuación te explicamos cómo combinar iterables utilizando zip():

fruits = ["apple", "orange", "banana"]
rating = [1, 2, 3]

fruits_rating = zip(rating, fruits)
print(list(fruits_rating))

En este ejemplo, fruits_rating empareja cada valoración con una fruta, creando una única iterable. El resultado es:

[(1, 'apple'), (2, 'orange'), (3, 'banana')]

Este código actúa como un sistema de puntuación para distintas frutas, con la primera lista (fruits) representando las frutas y la segunda lista representando las puntuaciones en una escala de 1 a 3.

3. Filter

Otra función avanzada, filter, toma 2 argumentos — una función y un iterable. Aplica la función a cada elemento del iterable y, a continuación, devuelve un nuevo iterable que contiene sólo aquellos elementos para los que la función devuelve un valor true. El siguiente ejemplo filtra una lista de valores enteros dentro de un rango determinado para devolver sólo los pares:

def is_even(n):
    return n%2 == 0

nums_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_list = filter(is_even, nums_list)
print(list(even_list))

En el código anterior, empiezas definiendo una función, is_even, para calcular un número par que se le pasa. A continuación, creas una lista de valores enteros entre 1 y 10 — nums_list. Por último, defines una nueva lista, even_list, que utiliza la función filter() para aplicar el método definido por el usuario a la lista original y devolver sólo los elementos pares de la lista. Éste es el resultado:

[2, 4, 6, 8, 10]

4. Map

Al igual que filter(), la función map() de Python toma como argumentos un iterable y una función. Pero en lugar de devolver elementos del iterable inicial, devuelve un nuevo iterable que contiene el resultado de la función aplicada a cada elemento del primer iterable. Para elevar al cuadrado una lista de enteros, utiliza la función map():

my_list = [2, 4, 6, 8, 10]
square_numbers = map(lambda x: x ** 2, my_list)
print(list(square_numbers))

En este código, x es el iterador que recorre la lista y la transforma mediante el cálculo del cuadrado. La función map() ejecuta esta operación tomando la lista original como argumento junto a una función de mapeo. El resultado es el siguiente

[4, 16, 36, 64, 100]

5. Sorted

La función sorted ordena los elementos de un iterable dado en un orden determinado (ascendente o descendente) y lo devuelve como una lista. Recibe un máximo de 3 parámetros: iterable, reverse(opcional) y key(opcional). Entonces, reverse por defecto es False, y si se establece en True, los elementos se ordenan en orden descendente. key es una función que calcula un valor para determinar el orden de clasificación del elemento en una iterable y por defecto es None.

Aquí tienes un ejemplo de cómo puedes aplicar la función sorted en varios iterables:

# set
py_set = {'e', 'a', 'u', 'o', 'i'}
print(sorted(py_set, reverse=True))

# dictionary
py_dict = {'e': 1, 'a': 2, 'u': 3, 'o': 4, 'i': 5}
print(sorted(py_dict, reverse=True))

# frozen set
frozen_set = frozenset(('e', 'a', 'u', 'o', 'i'))
print(sorted(frozen_set, reverse=True))

# string
string = "kinsta"
print(sorted(string))

# list
py_list = ['a', 'e', 'i', 'o', 'u']
print(py_list)

Esto te da la siguiente salida:

['u', 'o', 'i', 'e', 'a']
['u', 'o', 'i', 'e', 'a']
['u', 'o', 'i', 'e', 'a']
['a', 'i', 'k', 'n', 's', 't']
['a', 'e', 'i', 'o', 'u']

Cómo Manejar Casos Límite y Errores en Iterables

Los casos extremos son comunes en muchos escenarios de programación, y debes anticiparte a ellos en los iterables. Exploremos algunas posibilidades con las que te puedes encontrar.

1. Iterables Vacíos

Puedes encontrarte con problemas cuando un iterable está vacío, pero alguna lógica de programación intenta recorrerlo. Puedes abordar esto mediante programación para evitar ineficiencias. Aquí tienes un ejemplo que utiliza una sentencia if not para comprobar si una lista está vacía:

fruits_list=[]
if not fruits_list:
    print("The list is empty")

Éste es el resultado:

The list is empty

2. Iterables Anidados

Python también admite iterables anidados, que son objetos iterables que contienen otros iterables en su interior. Por ejemplo, puedes tener una lista de alimentos que contenga listas anidadas de categorías de alimentos, como carnes, verduras y cereales. A continuación te explicamos cómo modelar un escenario de este tipo utilizando iterables anidados:

food_list = [["kale", "broccoli", "ginger"], ["beef", "chicken", "tuna"], ["barley", "oats", "corn"]]
for inner_list in food_list:
    for food in inner_list:
        print(food)

En el código anterior, la variable food_list contiene tres listas anidadas, que representan diferentes categorías de alimentos. El bucle exterior (for inner_list in food_list:) itera a través de la lista primaria, y el bucle interior (for food in inner_list:) itera a través de cada lista anidada, imprimiendo cada alimento. El resultado es el siguiente:

kale
broccoli
ginger
beef
chicken
tuna
barley
oats
corn

3. Manejo de Excepciones

En Python, los iterables también admiten operaciones de gestión de excepciones. Por ejemplo, puedes iterar sobre una lista y encontrarte con un IndexError. Este error significa que estás intentando hacer referencia a un elemento que excede los límites del iterable. A continuación te explicamos cómo manejar una excepción de este tipo utilizando un bloque try-except:

fruits_list = ["apple", "mango", "orange", "pear"]
try:
    print(fruits_list[5])
except IndexError:
    print("The index specified is out of range.")

En el código anterior, el iterable fruits_list contiene cinco elementos asignados por los índices 0 a 5 en la colección de listas. La frase try contiene una función print que intenta mostrar el valor en el índice 5 del iterable, que no existe. Esto ejecuta la función except clause, returning the associated error message. The console returns the error:

The index specified is out of range.

Resumen

Dominar la iteración en Python es crucial para conseguir un código eficiente y legible. Comprender las distintas formas de iterar sobre diferentes estructuras de datos, utilizando comprensiones, generadores y aprovechando las funciones incorporadas, te convertirá en un programador de Python competente.

Tanto si trabajas con listas, diccionarios, cadenas u objetos personalizados, saber utilizar y manipular iterables es una habilidad indispensable en la programación en Python.

Cuando termines de crear tu aplicación Python y quieras alojarla en línea, prueba el Alojamiento de Aplicaciones de Kinsta. ¡Tus primeros 20 $ corren de nuestra cuenta!

¿Nos hemos dejado algo en esta guía? Por favor, ¡compártelo en la sección de comentarios más abajo!

Jeremy Holcombe Kinsta

Editor de Contenidos y Marketing en Kinsta, Desarrollador Web de WordPress y Redactor de Contenidos. Aparte de todo lo relacionado con WordPress, me gusta la playa, el golf y el cine. También tengo problemas con la gente alta ;).