Break y continue
Bucles Anidados, break y continue en Python
1. Qué son los bucles anidados
Un bucle anidado es simplemente un bucle dentro de otro bucle. El bucle interior se ejecuta completo en cada iteración del bucle exterior. Es como un reloj: el segundero da una vuelta completa por cada tick del minutero.
python
for exterior in range(3):
for interior in range(4):
print(f»exterior={exterior}, interior={interior}«)
«`
Salida:
«`
exterior=0, interior=0
exterior=0, interior=1
exterior=0, interior=2
exterior=0, interior=3
exterior=1, interior=0
exterior=1, interior=1
exterior=1, interior=2
exterior=1, interior=3
exterior=2, interior=0
exterior=2, interior=1
exterior=2, interior=2
exterior=2, interior=3
El bucle exterior se repite 3 veces. En cada una de esas repeticiones el bucle interior se repite 4 veces completas. Total de iteraciones: 3 × 4 = 12.
2. La indentación en bucles anidados
Cada nivel de anidamiento añade 4 espacios más. Es fundamental entender qué código pertenece a qué bucle:
python
for fila in range(3): # nivel 1 — bucle exterior
print(f»Fila {fila}:») # nivel 1 — se ejecuta 3 veces
for columna in range(4): # nivel 2 — bucle interior
print(f» Col {columna}«) # nivel 2 — se ejecuta 12 veces
print(«—«) # nivel 1 — después del interior, 3 veces
print(«Fin») # nivel 0 — una sola vez al terminar
«`
Salida:
«`
Fila 0:
Col 0
Col 1
Col 2
Col 3
—
Fila 1:
Col 0
Col 1
Col 2
Col 3
—
Fila 2:
Col 0
Col 1
Col 2
Col 3
—
Fin
3. Ejemplos reales de bucles anidados
Tablas de multiplicar
python
for tabla in range(1, 6):
print(f»\n Tabla del {tabla}«)
print(» « + «─» * 20)
for numero in range(1, 11):
resultado = tabla * numero
print(f» {tabla} × {numero:2} = {resultado:3}«)
«`
Salida:
«`
Tabla del 1
────────────────────
1 × 1 = 1
1 × 2 = 2
…
Tabla del 2
────────────────────
2 × 1 = 2
…
Matrices y cuadrículas
python
# Crear y mostrar una matriz de multiplicación
print(» «, end=«»)
for j in range(1, 6):
print(f»{j:4}«, end=«»)
print()
print(» « + «────» * 5)
for i in range(1, 6):
print(f»{i:2} │», end=«»)
for j in range(1, 6):
print(f»{i*j:4}«, end=«»)
print()
«`
Salida:
«`
1 2 3 4 5
────────────────────
1 │ 1 2 3 4 5
2 │ 2 4 6 8 10
3 │ 3 6 9 12 15
4 │ 4 8 12 16 20
5 │ 5 10 15 20 25
Patrones visuales
python
# Triángulo de asteriscos
n = 6
for fila in range(1, n + 1):
for col in range(fila):
print(«*», end=«»)
print()
«`
Salida:
«`
*
**
***
****
*****
******
python
# Diamante
n = 5
# Mitad superior
for fila in range(1, n + 1):
print(» « * (n – fila) + «*» * (2 * fila – 1))
# Mitad inferior
for fila in range(n – 1, 0, –1):
print(» « * (n – fila) + «*» * (2 * fila – 1))
«`
Salida:
«`
*
***
*****
*******
*********
*******
*****
***
*
Combinaciones y pares
python
# Todas las combinaciones de tallas y colores
tallas = [«S», «M», «L», «XL»]
colores = [«Rojo», «Azul», «Verde»]
print(«Variantes disponibles:»)
total = 0
for talla in tallas:
for color in colores:
total += 1
print(f» {total:2}. {talla} – {color}«)
print(f»\nTotal de variantes: {total}«)
«`
Salida:
«`
Variantes disponibles:
- S – Rojo
- S – Azul
- S – Verde
- M – Rojo
- M – Azul
…
- XL – Verde
Total de variantes: 12
Búsqueda en datos anidados
python
# Lista de alumnos, cada uno con sus notas
alumnos = [
{«nombre»: «Ana», «notas»: [8.5, 9.0, 7.8, 9.2]},
{«nombre»: «Carlos», «notas»: [4.8, 5.5, 6.0, 4.2]},
{«nombre»: «María», «notas»: [9.5, 8.7, 9.8, 9.1]},
{«nombre»: «Pedro», «notas»: [5.0, 4.5, 6.2, 5.8]},
]
print(f»{‘Alumno’:<10} {‘Notas’:<25} {‘Media’:>6} {‘Estado’}«)
print(«─» * 55)
for alumno in alumnos:
nombre = alumno[«nombre»]
notas = alumno[«notas»]
# Bucle interior para calcular la media
suma = 0
for nota in notas:
suma += nota
media = suma / len(notas)
notas_str = » «.join(str(n) for n in notas)
estado = «Aprobado» if media >= 5 else «Suspenso»
print(f»{nombre:<10} {notas_str:<25} {media:>6.2f} {estado}«)
«`
Salida:
«`
Alumno Notas Media Estado
───────────────────────────────────────────────────────
Ana 8.5 9.0 7.8 9.2 8.63 Aprobado
Carlos 4.8 5.5 6.0 4.2 5.13 Aprobado
María 9.5 8.7 9.8 9.1 9.28 Aprobado
Pedro 5.0 4.5 6.2 5.8 5.38 Aprobado
Bucles while anidados
Los bucles anidados no tienen por qué ser solo for. Puedes anidar while dentro de for, for dentro de while o while dentro de while:
python
# Sistema de niveles con intentos
niveles = [«Fácil», «Medio», «Difícil»]
respuestas_correctas = [«python», «bucle», «funcion»]
for i, nivel in enumerate(niveles):
print(f»\n=== Nivel {i+1}: {nivel} ===»)
intentos = 3
superado = False
while intentos > 0:
respuesta = input(f»Responde ({intentos} intentos): «).lower()
if respuesta == respuestas_correctas[i]:
print(«✓ ¡Correcto!»)
superado = True
break
else:
intentos -= 1
if intentos > 0:
print(f»✗ Incorrecto. Te quedan {intentos} intentos.»)
else:
print(f»✗ Sin intentos. La respuesta era ‘{respuestas_correctas[i]}‘.»)
if not superado:
print(«Game over. No has superado todos los niveles.»)
break
if superado:
print(«\n¡Enhorabuena! Has superado todos los niveles.»)
4. break — salir del bucle inmediatamente
break interrumpe el bucle en el momento en que se ejecuta, sin esperar a que la condición sea False ni a que se agoten los elementos. El programa continúa en la primera línea después del bucle.
python
for numero in range(1, 11):
if numero == 5:
break
print(numero, end=» «)
print(«\nEl bucle terminó»)
«`
Salida:
«`
1 2 3 4
El bucle terminó
En cuanto numero vale 5 se ejecuta break y el bucle termina. El 5 no se imprime porque break ocurre antes del print.
break en casos reales
Buscar el primer elemento que cumple una condición:
python
notas = [7.5, 8.0, 4.2, 9.1, 3.8, 6.5]
for i, nota in enumerate(notas):
if nota < 5:
print(f»Primer suspenso: nota {nota} en posición {i}«)
break
else:
print(«No hay suspensos»)
«`
Salida:
«`
Primer suspenso: nota 4.2 en posición 2
Validación con número máximo de intentos:
python
contrasena = «clave123»
max_intentos = 3
for intento in range(1, max_intentos + 1):
entrada = input(f»Intento {intento}/{max_intentos}: «)
if entrada == contrasena:
print(«✓ Acceso concedido.»)
break
else:
restantes = max_intentos – intento
if restantes > 0:
print(f»✗ Incorrecto. Quedan {restantes} intentos.»)
else:
print(«✗ Cuenta bloqueada por exceso de intentos.»)
«`
Ejecución fallida:
«`
Intento 1/3: hola
✗ Incorrecto. Quedan 2 intentos.
Intento 2/3: mundo
✗ Incorrecto. Queda 1 intento.
Intento 3/3: python
✗ Incorrecto. Quedan 0 intentos.
✗ Cuenta bloqueada por exceso de intentos.
Detener procesamiento al encontrar un error:
python
datos = [«25», «30», «ERROR», «45», «28»]
suma = 0
hay_error = False
for dato in datos:
if dato == «ERROR»:
print(f»Dato inválido encontrado: ‘{dato}‘. Procesamiento detenido.»)
hay_error = True
break
suma += int(dato)
if not hay_error:
print(f»Suma total: {suma}«)
else:
print(f»Suma parcial antes del error: {suma}«)
«`
Salida:
«`
Dato inválido encontrado: ‘ERROR’. Procesamiento detenido.
Suma parcial antes del error: 55
break en bucles anidados — comportamiento clave
Importante: break solo rompe el bucle más cercano en el que está, no todos los bucles anidados.
python
for exterior in range(3):
print(f»Exterior: {exterior}«)
for interior in range(5):
if interior == 2:
print(f» Break en interior={interior}«)
break # sale del bucle interior, no del exterior
print(f» Interior: {interior}«)
«`
Salida:
«`
Exterior: 0
Interior: 0
Interior: 1
Break en interior=2
Exterior: 1
Interior: 0
Interior: 1
Break en interior=2
Exterior: 2
Interior: 0
Interior: 1
Break en interior=2
El break sale del for interior pero el for exterior continúa. Para salir de ambos bucles a la vez necesitas una variable de control:
python
# Buscar un valor en una matriz y salir de ambos bucles
matriz = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
]
buscado = 7
encontrado = False
for fila in range(len(matriz)):
for col in range(len(matriz[fila])):
if matriz[fila][col] == buscado:
print(f»Encontrado {buscado} en fila {fila}, columna {col}«)
encontrado = True
break # sale del bucle interior
if encontrado:
break # sale del bucle exterior
if not encontrado:
print(f»{buscado} no está en la matriz»)
«`
Salida:
«`
Encontrado 7 en fila 1, columna 2
5. continue — saltar al siguiente ciclo
continue no termina el bucle, solo interrumpe la iteración actual y salta directamente a la siguiente. El código que hay después del continue en esa iteración no se ejecuta.
python
for numero in range(1, 11):
if numero % 2 == 0:
continue # salta los pares
print(numero, end=» «) # solo imprime los impares
«`
Salida:
«`
1 3 5 7 9
Cuando numero es par, continue se ejecuta y Python vuelve al inicio del bucle con el siguiente valor. El print solo se ejecuta en las iteraciones donde numero es impar.
continue en casos reales
Ignorar elementos no válidos:
python
datos = [8.5, –1, 6.0, 999, 7.5, –3, 9.0]
notas_validas = []
for dato in datos:
if dato < 0 or dato > 10:
print(f»Dato ignorado: {dato} (fuera de rango)»)
continue
notas_validas.append(dato)
print(f»\nNotas válidas: {notas_validas}«)
print(f»Media: {sum(notas_validas)/len(notas_validas):.2f}«)
«`
Salida:
«`
Dato ignorado: –1 (fuera de rango)
Dato ignorado: 999 (fuera de rango)
Dato ignorado: –3 (fuera de rango)
Notas válidas: [8.5, 6.0, 7.5, 9.0]
Media: 7.75
Procesar solo ciertos elementos:
python
alumnos = [
{«nombre»: «Ana», «nota»: 8.5, «asistencia»: 90},
{«nombre»: «Carlos», «nota»: 6.0, «asistencia»: 55},
{«nombre»: «María», «nota»: 9.2, «asistencia»: 95},
{«nombre»: «Pedro», «nota»: 7.5, «asistencia»: 60},
{«nombre»: «Lucía», «nota»: 8.0, «asistencia»: 88},
]
print(«Alumnos con asistencia suficiente (>= 70%):»)
print(«─» * 40)
for alumno in alumnos:
if alumno[«asistencia»] < 70:
print(f» {alumno[‘nombre’]:<10} → Excluido por asistencia ({alumno[‘asistencia’]}%)»)
continue
estado = «Aprobado» if alumno[«nota»] >= 5 else «Suspenso»
print(f» {alumno[‘nombre’]:<10} {alumno[‘nota’]} {estado}«)
«`
Salida:
«`
Alumnos con asistencia suficiente (>= 70%):
────────────────────────────────────────
Ana 8.5 Aprobado
Carlos → Excluido por asistencia (55%)
María 9.2 Aprobado
Pedro → Excluido por asistencia (60%)
Lucía 8.0 Aprobado
Saltar números con ciertas propiedades:
python
# Imprimir solo números que no son divisibles ni por 2 ni por 3
print(«Números del 1 al 30 no divisibles por 2 ni por 3:»)
for n in range(1, 31):
if n % 2 == 0 or n % 3 == 0:
continue
print(n, end=» «)
«`
Salida:
«`
1 5 7 11 13 17 19 23 25 29
continue en bucles anidados
Al igual que break, continue afecta solo al bucle más cercano:
python
for exterior in range(3):
for interior in range(5):
if interior == 2:
continue # salta solo esta iteración del interior
print(f»ext={exterior}, int={interior}«, end=» «)
print()
«`
Salida:
«`
ext=0, int=0 ext=0, int=1 ext=0, int=3 ext=0, int=4
ext=1, int=0 ext=1, int=1 ext=1, int=3 ext=1, int=4
ext=2, int=0 ext=2, int=1 ext=2, int=3 ext=2, int=4
El valor interior=2 nunca aparece porque se salta con continue, pero el resto de iteraciones tanto del interior como del exterior continúan con normalidad.
6. Diferencia clave entre break y continue
python
numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Con CONTINUE — salta el 5, sigue con el resto
print(«Con continue:»)
for n in numeros:
if n == 5:
continue
print(n, end=» «)
# 1 2 3 4 6 7 8 9 10
print(«\n\nCon break:»)
# Con BREAK — para en el 5, no procesa más
for n in numeros:
if n == 5:
break
print(n, end=» «)
# 1 2 3 4
La diferencia es clara: continue evita el elemento actual pero sigue con los demás. break detiene el bucle por completo.
7. Ejemplo completo — todo junto
Este ejemplo usa bucles anidados, break y continue de forma coordinada:
python
# Sistema de examen con preguntas y niveles
preguntas_por_nivel = {
«Básico»: [
(«¿Qué función imprime en pantalla?», «print»),
(«¿Qué tipo es True?», «bool»),
(«¿Cuánto es 5 % 2?», «1»),
],
«Medio»: [
(«¿Qué hace break?», «salir del bucle»),
(«¿Qué devuelve len(‘hola’)?», «4»),
(«¿Cómo se declara una lista vacía?», «[]»),
],
}
puntuacion_total = 0
examen_completado = True
for nivel, preguntas in preguntas_por_nivel.items():
print(f»\n{‘=’*40}«)
print(f» NIVEL: {nivel}«)
print(f»{‘=’*40}«)
puntuacion_nivel = 0
nivel_superado = True
for i, (pregunta, respuesta_correcta) in enumerate(preguntas, 1):
print(f»\nPregunta {i}: {pregunta}«)
intentos = 2
while intentos > 0:
respuesta = input(«Tu respuesta: «).strip().lower()
if respuesta == respuesta_correcta.lower():
if intentos == 2:
puntos = 2
print(«✓ ¡Correcto a la primera! +2 puntos»)
else:
puntos = 1
print(«✓ ¡Correcto! +1 punto»)
puntuacion_nivel += puntos
break
else:
intentos -= 1
if intentos > 0:
print(f»✗ Incorrecto. Tienes {intentos} intento más.»)
else:
print(f»✗ Incorrecto. Era: ‘{respuesta_correcta}‘»)
nivel_superado = False
puntuacion_total += puntuacion_nivel
print(f»\nPuntuación en {nivel}: {puntuacion_nivel}/{len(preguntas)*2}«)
if not nivel_superado:
print(f»No has superado el nivel {nivel}. Fin del examen.»)
examen_completado = False
break # sale del bucle de niveles
print(f»\n{‘=’*40}«)
print(f» RESULTADO FINAL»)
print(f»{‘=’*40}«)
print(f»Puntuación total: {puntuacion_total}«)
if examen_completado:
print(«¡Has completado todos los niveles!»)
else:
print(«No has completado el examen.»)
«`
—
## Resumen visual
«`
BUCLES ANIDADOS
───────────────
for exterior in …: ← se ejecuta N veces
for interior in …: ← se ejecuta N×M veces en total
codigo ← código más interno
BREAK
─────
for elemento in secuencia:
if condicion:
break ← sale del bucle inmediatamente
codigo_normal ← no se ejecuta si hay break
CONTINUE
────────
for elemento in secuencia:
if condicion:
continue ← salta al siguiente elemento
codigo_normal ← no se ejecuta en la iteración saltada
EN ANIDADOS
───────────
for exterior:
for interior:
break ← sale solo del interior, exterior continúa
continue ← salta solo en el interior, exterior continúa
Reglas de oro: los bucles anidados multiplican las iteraciones, así que úsalos con cuidado en colecciones muy grandes. break y continue afectan siempre al bucle más cercano en que están. Para salir de varios niveles a la vez usa una variable booleana de control. continue es útil para filtrar elementos no deseados sin anidar más if. break es útil cuando ya encontraste lo que buscabas y no tiene sentido seguir iterando.