Bucles anidados en Python: patrones, velocidad y cuándo evitarlos
Esta lección es una traducción del original en inglés.Read in EnglishAvisar de un error de traducción
Piensa en una hoja de cálculo. Tiene filas y columnas. Para leer cada celda, recorres cada fila y, dentro de cada fila, recorres cada columna. Son dos bucles, uno dentro del otro. Eso es un bucle anidado.
Los bucles anidados aparecen por todas partes en programación: para imprimir patrones en forma de cuadrícula, buscar en tablas, generar combinaciones y procesar imágenes píxel a píxel. Son muy útiles, pero también pueden ser sorprendentemente lentos si no tienes cuidado.
En esta lección aprenderás cómo funcionan los bucles anidados, verás ejemplos prácticos con cuadrículas y combinaciones, entenderás por qué pueden ser lentos y descubrirás cuándo conviene usar otra solución.
¿Cómo funcionan los bucles anidados en Python?
Un bucle anidado es un bucle dentro de otro bucle. El bucle externo arranca primero. En cada iteración del bucle externo, el bucle interno se ejecuta completo, de principio a fin.
(1,1) (1,2) (1,3) (2,1) (2,2) (2,3) (3,1) (3,2) (3,3)
Esta es la idea clave: si el bucle externo se ejecuta n veces y el bucle interno m veces, el código dentro del bucle interno se ejecuta n x m veces en total. Con tres filas y tres columnas, se imprime 9 veces.
Total iterations: 15
Trabajar con datos en 2D (cuadrículas y tablas)
El uso más práctico de los bucles anidados es trabajar con datos bidimensionales. En Python, una lista de listas representa una cuadrícula, una tabla o una matriz. El bucle externo recorre las filas y el bucle interno recorre las columnas de cada fila.
1 2 3 4 5 6 7 8 9
A veces necesitas el índice de la fila y de la columna, no solo los valores. Para eso, usa enumerate().
X found at row 0, col 0 X found at row 0, col 2 X found at row 1, col 1 X found at row 2, col 2
Veamos un ejemplo práctico: construir una tabla de multiplicar.
1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25
Generar combinaciones con bucles anidados
Los bucles anidados son perfectos para generar todas las combinaciones de elementos de dos (o más) grupos. El bucle externo elige del primer grupo y el bucle interno elige del segundo.
All t-shirt options: red - S red - M red - L blue - S blue - M blue - L
Con 2 colores y 3 tallas, obtienes 6 combinaciones. Cada color se combina con cada talla. Esto se llama producto cartesiano de las dos listas.
Pairs that sum to 10: 1 + 9 = 10 3 + 7 = 10
Crear patrones con bucles anidados
Imprimir patrones es un ejercicio clásico para entender los bucles anidados. El bucle externo controla cada fila, y el bucle interno controla cuántos caracteres tiene cada fila.
* ** *** **** *****
El truco está en que el rango del bucle interno depende de la variable del bucle externo. En la fila 1, el bucle interno se ejecuta una vez. En la fila 2, dos veces. En la fila 5, cinco veces. Eso crea la forma de escalera.
***** **** *** ** *
Rendimiento: por qué los bucles anidados pueden ser lentos
Un bucle sencillo sobre 1000 elementos se ejecuta 1000 veces. Un bucle anidado sobre esos 1000 elementos se ejecuta 1000 x 1000 = 1 000 000 de veces. Eso es un millón de operaciones. Añade un tercer nivel de anidamiento y llegas a mil millones. Los bucles anidados multiplican, y las cifras crecen muy rápido.
En informática, esto se describe con la notación Big O (notación O grande). Un bucle sencillo es O(n): el tiempo crece de forma lineal con el tamaño de los datos. Un bucle anidado es O(n²): el tiempo crece con el cuadrado del tamaño de los datos. Si duplicas la entrada, el trabajo se multiplica por cuatro.
Cuándo evitar los bucles anidados
No todos los problemas que parecen pedir bucles anidados los necesitan de verdad. A menudo hay una forma más rápida con conjuntos, diccionarios o funciones integradas.
nums = [3, 1, 4, 1, 5, 9]
has_dup = False
for i in range(len(nums)):
for j in range(i+1, len(nums)):
if nums[i] == nums[j]:
has_dup = True
print(has_dup) # Truenums = [3, 1, 4, 1, 5, 9]
has_dup = len(nums) != len(set(nums))
print(has_dup) # TrueLa versión con un conjunto no solo es más corta: es muchísimo más rápida. Con 10 000 elementos, la versión con bucle anidado hace 50 millones de comparaciones. La versión con conjunto hace unas 10 000 operaciones. Es 5000 veces más rápida.
students = [
{'name': 'Alice', 'id': 101},
{'name': 'Bob', 'id': 102},
{'name': 'Charlie', 'id': 103}
]
ids_to_find = [103, 101]
for target_id in ids_to_find:
for s in students:
if s['id'] == target_id:
print(s['name'])students = [
{'name': 'Alice', 'id': 101},
{'name': 'Bob', 'id': 102},
{'name': 'Charlie', 'id': 103}
]
ids_to_find = [103, 101]
lookup = {s['id']: s['name'] for s in students}
for target_id in ids_to_find:
print(lookup[target_id])Ejercicios de práctica
Estos ejercicios afianzarán lo que sabes de los bucles anidados. Empiezan con patrones básicos y avanzan hacia problemas del mundo real.
Imprime un rectángulo de asteriscos de 3 filas y 5 columnas. Cada fila debe tener 5 asteriscos, sin espacios entre ellos.
Salida esperada:
*****
*****
*****Sin ejecutar el código, predice qué va a imprimir. Cuenta cuántas líneas tiene la salida en total. Después, ejecútalo para comprobarlo.
Imprime un triángulo de números en el que cada fila contiene su número de fila repetido. El triángulo tiene 4 filas.
Salida esperada:
1
22
333
4444Tienes una cuadrícula de números. Usa bucles anidados para calcular e imprimir la suma de todos sus valores.
Salida esperada:
45Dada una lista de prendas de arriba (tops) y otra de prendas de abajo (bottoms), imprime todas las combinaciones posibles y, al final, el total.
Salida esperada:
shirt + jeans
shirt + shorts
sweater + jeans
sweater + shorts
hoodie + jeans
hoodie + shorts
Total outfits: 6Este código debería imprimir una cuadrícula de coordenadas de 3x3, pero tiene un error. La salida debe mostrar cada fila de coordenadas en su propia línea, donde tanto x como y van de 0 a 2.
Salida esperada:
(0,0) (0,1) (0,2)
(1,0) (1,1) (1,2)
(2,0) (2,1) (2,2)Encuentra el error y corrígelo.
Resumen: bucles anidados en Python
Esto es lo que aprendiste sobre los bucles anidados:
| Concepto | Idea clave |
|---|---|
| Bucle anidado | Un bucle dentro de otro bucle |
| Iteraciones totales | Vueltas del externo x vueltas del interno |
| Datos 2D | Bucle externo = filas, bucle interno = columnas |
| Combinaciones | Emparejar cada elemento del grupo A con cada elemento del grupo B |
| Rendimiento | O(n²): si duplicas la entrada, el trabajo se multiplica por cuatro |
| Alternativas | Los conjuntos y los diccionarios a menudo sustituyen a los bucles anidados |
Reglas prácticas:
'*' * n) suele sustituir al bucle interno en los patrones¿Qué sigue?
En la siguiente lección, [Cómo leer los mensajes de error de Python](/python/python-error-messages), aprenderás a descifrar los mensajes de error de Python, a corregir los errores más comunes y a dejar de temerle al traceback (rastreo de errores). Saber depurar facilita todo lo demás.