🔁 2.3 Bucles y Control de Iteración
Aprende a automatizar tareas con los bucles de Python: for
, while
,
las palabras clave break
, continue
, pass
y la iteración sobre colecciones.
- Parte 1 — Bucle for,
for
conrange()
y recorrido de colecciones - Parte 2 — Bucle while y simulación de do-while
- Parte 3 — Palabras clave
break
,continue
ypass
- Parte 4 — Bucles anidados y control de flujo
- Parte 5 — Iteración avanzada:
iter()
,enumerate()
yzip()
- Parte 6 — Ejercicios prácticos, rendimiento y resumen final
🔁 Parte 1 — Bucle for
, for
con range()
y recorrido de colecciones
El bucle for
en Python recorre elementos de un iterable (listas, tuplas, cadenas, diccionarios, sets, rangos, etc.).
A diferencia de otros lenguajes, for
en Python no usa un índice numérico por defecto; en su lugar, itera directamente sobre los elementos.
✅ Sintaxis básica de for
# Recorrer una lista de nombres
nombres = ["Ana", "Luis", "Sofía"]
for nombre in nombres:
print("Hola,", nombre)
Lee la frase como: “para cada nombre
en nombres
, ejecuta el bloque”. Es directo y muy legible.
📦 ¿Qué es un iterable?
Un iterable es un objeto que se puede recorrer elemento a elemento: listas, tuplas, diccionarios, conjuntos, cadenas, objetos de range()
, etc.
Más adelante (Parte 5) veremos iter()
, enumerate()
y zip()
para iteración avanzada.
📚 Recorrer las colecciones más comunes
Colección | Qué recorre | Ejemplo |
---|---|---|
Lista / Tupla | Elementos en orden |
|
Cadena (str ) | Caracteres |
|
Diccionario (dict ) | Claves por defecto |
|
Conjunto (set ) | Elementos únicos (sin orden garantizado) |
|
🎯 Iteración indexada: cuándo y cómo
Si necesitas el índice, evita contadores manuales. Lo más claro es usar enumerate()
(lo verás en detalle en la Parte 5). Vista rápida:
frutas = ["manzana", "pera", "uva"]
for i, fruta in enumerate(frutas):
print(i, fruta)
Solo usa índices cuando sea necesario; por defecto, itera por elementos (código más limpio y menos errores).
📏 range()
: generador de secuencias numéricas
range()
crea una secuencia de enteros eficiente en memoria. Muy útil para repetir acciones N veces o generar índices.
Firma | Significado | Ejemplo | Secuencia |
---|---|---|---|
range(stop) | 0 hasta stop-1 | range(5) | 0,1,2,3,4 |
range(start, stop) | start hasta stop-1 | range(2, 6) | 2,3,4,5 |
range(start, stop, step) | Salto step (positivo o negativo) | range(10, 0, -2) | 10,8,6,4,2 |
# Repetir 5 veces
for _ in range(5):
print("¡Hola!")
# Recorrer índices de una lista (si lo necesitas)
frutas = ["manzana", "pera", "uva"]
for i in range(len(frutas)):
print(i, frutas[i])
# Contar hacia atrás
for n in range(5, 0, -1):
print(n)
range()
es exclusivo. range(5)
llega hasta 4.🧠 for
… else
: el else de los bucles
El bloque else
se ejecuta si el for
termina sin encontrar un break
. Útil para búsquedas.
numeros = [2, 4, 6, 8]
buscado = 5
for n in numeros:
if n == buscado:
print("Encontrado")
break
else:
print("No encontrado") # Solo se ejecuta si NO hubo break
🧼 Patrones seguros al iterar
1) No modifiques una lista mientras la recorres
Si necesitas mutarla, itera sobre una copia o construye una nueva lista.
# 👎 Riesgo de comportamientos extraños
for x in lista:
if condicion(x):
lista.remove(x)
# 👍 Seguro (copia superficial)
for x in lista[:]:
if condicion(x):
lista.remove(x)
# 👍 Mejor: filtra y reasigna
lista = [x for x in lista if not condicion(x)]
2) Itera por elementos, no por índices (cuando sea posible)
# 👎 Verboso e innecesario
for i in range(len(nombres)):
print(nombres[i])
# 👍 Idiomático
for nombre in nombres:
print(nombre)
3) Costes de operaciones dentro del bucle
Evita repetir cálculos o accesos caros dentro del bucle; guarda referencias locales.
# 👎 Llamada repetida costosa
for i in range(len(data())):
procesar(data()[i])
# 👍 Cachea resultados
d = data()
for item in d:
procesar(item)
🧮 Ejemplos típicos con for
A) Sumar elementos
numeros = [3, 5, 7]
suma = 0
for n in numeros:
suma += n
print("Suma =", suma)
B) Contar elementos que cumplen una condición
palabras = ["python", "java", "go", "php"]
contador = 0
for p in palabras:
if len(p) >= 4:
contador += 1
print("Con 4+ letras:", contador)
C) Recorrer un diccionario (claves, valores, pares)
config = {"host": "localhost", "port": 5432}
for k in config: # claves
print(k)
for v in config.values(): # valores
print(v)
for k, v in config.items(): # pares
print(k, "=", v)
🌱 Introducción a comprensiones (teaser)
Las comprensiones crean colecciones a partir de iterables de forma concisa. Las verás en profundidad más adelante, pero aquí va una muestra:
# Lista con cuadrados de 1..5
cuadrados = [n * n for n in range(1, 6)]
print(cuadrados) # [1, 4, 9, 16, 25]
for
tradicional por legibilidad.🧪 Mini-ejercicios
- Imprime los números del 1 al 10 usando
range()
. Luego, del 10 al 1 con paso negativo. - Recorre la cadena
"Programación"
y cuenta cuántas vocales contiene. - Dado el diccionario
{"a":1,"b":2,"c":3}
, genera una salida “a=1, b=2, c=3
”. - Crea una lista con los múltiplos de 3 entre 1 y 30 usando
for
y otra con comprensión; compara. - Usa
for ... else
para buscar un elemento en una lista y reportar si no está.
🏁 Conclusión
Has visto el corazón de la iteración en Python: for
sobre iterables y range()
para secuencias numéricas.
En la Ahora abordarás while
y la forma idiomática de simular do-while en Python, con patrones de ruptura controlada.
⏳ Parte 2 — Bucle while
y simulación de do-while
El bucle while
repite un bloque de código mientras una condición sea verdadera.
A diferencia de for
, que recorre elementos de un iterable, while
es ideal cuando no conoces de antemano cuántas iteraciones necesitarás (por ejemplo, leer entradas hasta que el usuario escriba “salir”).
✅ Sintaxis básica de while
contador = 1
while contador <= 5:
print("Iteración", contador)
contador += 1
- La condición se evalúa antes de cada vuelta.
- Hay que actualizar el estado (ej. incrementar contadores) para evitar bucles infinitos.
🧭 Casos de uso típicos
Patrón | Descripción | Ejemplo |
---|---|---|
Contador | Repite N veces con una condición numérica |
|
Centinela | Repite hasta leer un valor “sentinel” (p. ej., «salir») |
|
Validación | Insiste hasta que la entrada sea válida |
|
🧠 while
… else
: el else de los bucles
El bloque else
se ejecuta cuando el while
termina sin un break
. Útil para búsquedas o intentos acotados.
objetivo = 37
n = 1
while n * n <= 1000:
if n * n == objetivo:
print("Raíz exacta encontrada:", n)
break
n += 1
else:
print("No hay raíz entera para", objetivo)
🧪 Simulación de do-while en Python
Python no tiene do-while
nativo (ejecuta al menos una vez y luego comprueba). Se emula con while True
+ break
al final del ciclo.
Patrón general
while True:
# 1) Hacer trabajo al menos una vez
comando = input("Comando (salir para terminar): ")
# 2) Validar / decidir
if comando == "salir":
break
# 3) Continuar si procede
print("Procesado:", comando)
Ejemplo: leer un número (al menos una vez) y validar
while True:
dato = input("Introduce un número positivo: ")
if dato.replace('.', '', 1).isdigit() and float(dato) > 0:
numero = float(dato)
break
print("Valor no válido. Intenta de nuevo.")
print("Número OK:", numero)
🛡️ Evitar bucles infinitos
- Asegúrate de que algo cambia en cada iteración (contadores, lectura de nueva entrada, etc.).
- Si usas
while True
, define condiciones de salida claras conbreak
.
# 👎 Infinite loop potencial (i nunca cambia)
i = 0
while i < 5:
print(i)
# falta: i += 1
# 👍 Corrección
i = 0
while i < 5:
print(i)
i += 1
⚙️ break
, continue
y pass
con while
(vista rápida)
# break: sale del bucle
i = 0
while i < 10:
if i == 5:
break
print(i)
i += 1
# continue: salta a la siguiente iteración
i = 0
while i < 5:
i += 1
if i % 2 == 0:
continue
print("Impar:", i)
# pass: placeholder (no hace nada, útil como “TODO”)
while False:
pass
Verás estos keywords en detalle en la Parte 3.
🧩 Patrones prácticos de while
1) Reintentos con límite
intentos = 0
MAX_INTENTOS = 3
while intentos < MAX_INTENTOS:
pwd = input("Password: ")
if pwd == "secreto":
print("Acceso concedido")
break
intentos += 1
else:
print("Cuenta bloqueada por demasiados intentos")
2) Acumular hasta centinela
total = 0.0
while True:
s = input("Importe (ENTER para terminar): ").strip()
if s == "":
break
if s.replace('.', '', 1).isdigit():
total += float(s)
else:
print("Número inválido:", s)
print("Total =", total)
3) Polling con espera (simulado)
import time
estado = "pendiente"
reintentos = 0
while estado != "completado" and reintentos < 5:
print("Consultando estado...")
time.sleep(1) # espera 1 segundo (ejemplo)
# Simulación: cambia estado en el 3er intento
reintentos += 1
if reintentos == 3:
estado = "completado"
print("Estado final:", estado)
🧼 Buenas prácticas con while
- Prefiere
for
cuando iteras colecciones; usawhile
para condiciones abiertas o bucles controlados por eventos. - Declara claramente el estado que gobierna la salida del bucle.
- Evita condiciones complejas: extrae booleanos con nombre (
cond_ok
,entradas_restantes
…). - Para “al menos una vez”, usa el patrón
while True
+break
(do-while).
🧪 Mini-ejercicios
- Solicita números al usuario y calcula la media. Termina cuando escriba “fin”.
- Pide una contraseña y confirma que tenga al menos 8 caracteres, 1 mayúscula y 1 número. Insiste hasta que cumpla.
- Implementa un contador regresivo desde un número N hasta 0 con
while
. - Simula un do-while que pida “¿Deseas continuar? (s/n)” y solo acepte
s
on
. - Escribe un
while ... else
que busque un valor en una lista y notifique si no aparece.
🏁 Conclusión
El bucle while
es tu aliado cuando la iteración depende de una condición dinámica.
Con el patrón do-while emulado, cubres la necesidad de ejecutar al menos una vez.
En la Ahora profundizaremos en las palabras clave break
, continue
y pass
, y cómo controlan el flujo dentro de cualquier bucle.
⚙️ Parte 3 — Palabras clave break
, continue
y pass
Python ofrece tres instrucciones especiales para controlar el flujo dentro de un bucle:
break
, continue
y pass
.
Con ellas puedes detener, saltar o mantener la estructura del bucle según las condiciones.
🚪 break
: salir del bucle inmediatamente
break
interrumpe el bucle actual, incluso si la condición todavía se cumple.
Es útil para terminar cuando se encuentra un resultado, error o evento esperado.
# Buscar un número en una lista
numeros = [2, 4, 6, 8, 10]
buscado = 6
for n in numeros:
if n == buscado:
print("Encontrado:", n)
break
print("Comprobando", n)
print("Fin del bucle")
📌 Aquí el break
detiene el bucle en cuanto encuentra el valor buscado.
💡 Con while
contador = 0
while True:
contador += 1
print("Intento", contador)
if contador == 3:
print("¡Máximo alcanzado!")
break
En un while True
, break
es la condición de salida. Es la forma más común de crear bucles con fin controlado manualmente.
🧠 Uso combinado con else
Cuando se usa con for
o while
, el bloque else
solo se ejecuta si no hubo un break
.
for n in [1, 2, 3, 4]:
if n == 99:
print("Encontrado")
break
else:
print("No se encontró el valor")
🔁 continue
: saltar a la siguiente iteración
continue
interrumpe la iteración actual y pasa directamente a la siguiente vuelta del bucle.
Se usa para ignorar casos que no queremos procesar, sin detener el bucle completo.
# Mostrar solo números impares
for n in range(1, 8):
if n % 2 == 0:
continue
print("Impar:", n)
✅ Los valores pares se saltan; el resto se procesan normalmente.
Ejemplo con while
n = 0
while n < 5:
n += 1
if n == 3:
continue # salta la impresión de 3
print("Número:", n)
🧩 Comparación entre break
y continue
Palabra clave | Qué hace | Ejemplo visual |
---|---|---|
break | Detiene todo el bucle |
|
continue | Salta a la siguiente iteración |
|
🪟 pass
: “no hacer nada” (placeholder)
pass
sirve como bloque vacío: mantiene la estructura del código cuando aún no hay implementación.
Python exige que los bloques (if
, for
, def
…) contengan al menos una instrucción.
Si todavía no tienes nada que ejecutar, pass
evita errores de sintaxis.
# Ejemplo en un if
edad = 17
if edad >= 18:
print("Mayor de edad")
else:
pass # pendiente de implementar
También se usa en clases o funciones que están “por definir”.
def procesar_datos():
pass # TODO: implementar lógica más adelante
class Usuario:
pass # estructura vacía temporal
⚙️ Ejemplo práctico integrador
Veamos cómo se combinan break
, continue
y pass
en un programa con flujo controlado:
# Procesar una lista de tareas
tareas = ["leer", "dormir", "escribir", "salir", "pasear"]
for tarea in tareas:
if tarea == "salir":
print("🚪 Fin de la sesión")
break
elif tarea == "dormir":
print("😴 Saltando tarea no productiva")
continue
elif tarea == "escribir":
pass # futuro: guardar en base de datos
print("✅ Ejecutando:", tarea)
💡 Salida esperada:
✅ Ejecutando: leer
😴 Saltando tarea no productiva
✅ Ejecutando: escribir
🚪 Fin de la sesión
🧠 Cuándo usar cada una
Instrucción | Propósito | Uso típico |
---|---|---|
break | Salir del bucle completamente | Cuando se cumple una condición o se detecta un error |
continue | Saltar a la siguiente vuelta | Ignorar casos no válidos o que no aplican |
pass | Marcador de posición | Bloques vacíos en desarrollo |
🧩 Errores comunes
- ❌ Olvidar
break
en unwhile True
→ bucle infinito. - ❌ Usar
continue
sin actualizar variables → misma condición repetida. - ❌ Colocar
pass
creyendo que ejecuta algo → no hace nada realmente.
🧪 Mini-ejercicios
- Recorre una lista de nombres y detente con
break
cuando aparezca “fin”. - Imprime los números del 1 al 10, pero omite los múltiplos de 3 con
continue
. - Crea una función
menu()
que repita opciones hasta que el usuario escriba “salir”. Usawhile True
ybreak
. - Declara una clase vacía
Persona
y una funciónpendiente()
conpass
dentro. - Haz una búsqueda en una lista usando
for ... else
ybreak
si se encuentra el valor.
🏁 Conclusión
Las palabras clave break
, continue
y pass
te permiten afinar el control de flujo en cualquier bucle.
Dominar su uso te dará un código más expresivo, flexible y limpio.
En la Ahora aprenderás a combinar bucles anidados (uno dentro de otro) y cómo aplicar estas palabras clave para optimizar tus recorridos más complejos.
🔂 Parte 4 — Bucles anidados y control de flujo
Los bucles anidados permiten ejecutar un bucle dentro de otro.
Son útiles cuando se trabaja con estructuras bidimensionales (listas de listas, matrices, tablas, cuadrículas, etc.)
o cuando una tarea necesita repetir otra tarea interna varias veces.
✅ Sintaxis general
for externo in iterable_externo:
for interno in iterable_interno:
# código a ejecutar por cada combinación
...
Esto se traduce como: “por cada elemento del bucle externo, recorre todos los elementos del bucle interno”.
El número total de iteraciones es el producto de ambos tamaños (len(outer) * len(inner)
).
📦 Ejemplo 1 — Tabla de multiplicar
for i in range(1, 4): # bucle externo
for j in range(1, 4): # bucle interno
print(f"{i} × {j} = {i*j}")
print("-- Fin del bloque de", i)
💡 Salida:
1 × 1 = 1
1 × 2 = 2
1 × 3 = 3
-- Fin del bloque de 1
2 × 1 = 2
2 × 2 = 4
2 × 3 = 6
-- Fin del bloque de 2
...
Cada ciclo externo (i
) activa un recorrido completo del ciclo interno (j
).
📊 Ejemplo 2 — Recorrer listas de listas (matriz)
# Matriz de 3x3
matriz = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
for fila in matriz:
for valor in fila:
print(valor, end=" ")
print()
💡 Salida:
1 2 3
4 5 6
7 8 9
✅ El bucle externo recorre las filas, y el interno los valores dentro de cada fila.
🧠 Ejemplo 3 — Diccionarios anidados
Cuando un diccionario contiene otros diccionarios, puedes usar bucles anidados para recorrer las claves y valores internos.
usuarios = {
"javier": {"rol": "admin", "activo": True},
"ana": {"rol": "editor", "activo": False}
}
for usuario, datos in usuarios.items():
print(f"👤 {usuario}:")
for clave, valor in datos.items():
print(f" {clave} = {valor}")
💡 Salida:
👤 javier:
rol = admin
activo = True
👤 ana:
rol = editor
activo = False
🔍 Ejemplo 4 — Búsqueda con break
en bucles anidados
El uso de break
en bucles anidados solo rompe el bucle interno, no el externo.
Si quieres detener ambos, debes usar una bandera o una función auxiliar.
matriz = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
buscado = 5
encontrado = False
for fila in matriz:
for valor in fila:
if valor == buscado:
print("Encontrado:", valor)
encontrado = True
break # rompe el bucle interno
if encontrado:
break # rompe el externo
print("Búsqueda completada")
💡 Salida: detiene ambos bucles al encontrar el número.
⚙️ Ejemplo 5 — Generar coordenadas (x, y)
Los bucles anidados son muy útiles para generar combinaciones o pares de valores.
for x in range(3):
for y in range(3):
print(f"({x}, {y})")
📏 Total de iteraciones: 3 × 3 = 9.
💡 Control del flujo en bucles anidados
Palabra clave | Efecto en bucles anidados | Ejemplo |
---|---|---|
break | Sale del bucle interno |
|
continue | Salta la iteración interna actual |
|
pass | No hace nada (reserva de bloque) |
|
📦 Ejemplo 6 — Patrón con bucles anidados (pirámide)
# Pirámide simple
filas = 5
for i in range(1, filas + 1):
for j in range(i):
print("*", end="")
print()
💡 Salida:
*
**
***
****
*****
El bucle interno imprime los asteriscos, y el externo controla la cantidad de filas.
🧮 Ejemplo 7 — Matriz transpuesta (for anidados)
Transformar filas en columnas con bucles anidados:
matriz = [
[1, 2, 3],
[4, 5, 6]
]
filas = len(matriz)
columnas = len(matriz[0])
transpuesta = []
for j in range(columnas):
fila_nueva = []
for i in range(filas):
fila_nueva.append(matriz[i][j])
transpuesta.append(fila_nueva)
print(transpuesta)
💡 Salida: [[1, 4], [2, 5], [3, 6]]
🧩 Ejemplo 8 — Triple bucle
También se pueden anidar tres bucles o más, pero esto debe hacerse solo cuando sea necesario (afecta el rendimiento).
for x in range(2):
for y in range(2):
for z in range(2):
print(f"({x},{y},{z})")
📏 Total de iteraciones: 2 × 2 × 2 = 8.
🧠 Buenas prácticas con bucles anidados
- ⚙️ Usa bucles anidados solo cuando sea necesario. Evalúa si puedes usar funciones, listas por comprensión o
itertools
. - 📉 La complejidad aumenta rápidamente: un doble bucle es
O(n²)
, un tripleO(n³)
. - 💡 Usa
break
ycontinue
para acortar ejecuciones innecesarias. - 🧱 Refactoriza: si el bucle interno crece, muévelo a una función auxiliar.
- 🧩 Usa nombres descriptivos en lugar de
i, j, k
si el contexto lo permite.
🧪 Mini-ejercicios
- Genera la tabla de multiplicar del 1 al 10 usando bucles anidados.
- Imprime una cuadrícula 5×5 de coordenadas
(x, y)
. - Dada una lista de listas, muestra la suma de cada sublista.
- Convierte una matriz 3×3 en su transpuesta usando bucles.
- Crea un triángulo de números con doble bucle, como:
1 1 2 1 2 3 1 2 3 4
🏁 Conclusión
Los bucles anidados son potentes y flexibles, pero deben usarse con prudencia.
Son el pilar del procesamiento de estructuras complejas como matrices, tablas y datos multidimensionales.
En la Ahora aprenderás a dominar la iteración avanzada con enumerate()
, zip()
e iteradores personalizados para escribir código aún más eficiente y expresivo.
⚙️ Parte 5 — Iteración avanzada: iter()
, enumerate()
y zip()
Hasta ahora has aprendido a recorrer colecciones con for
y while
.
En esta sección veremos técnicas avanzadas de iteración que hacen tu código más legible, eficiente y profesional:
iter()
— Convierte objetos en iteradores manuales.enumerate()
— Añade índices automáticamente durante un bucle.zip()
— Combina varios iterables en paralelo.
🧩 1. iter()
: crear un iterador manualmente
Un iterador es un objeto que devuelve elementos uno a uno cuando se usa en un bucle.
La función iter()
devuelve un iterador a partir de una colección o secuencia.
frutas = ["manzana", "pera", "uva"]
it = iter(frutas) # crea un iterador
print(next(it)) # manzana
print(next(it)) # pera
print(next(it)) # uva
# print(next(it)) → StopIteration
💡 Cuando se acaba el iterador, lanza una excepción StopIteration
.
Por eso los bucles for
la gestionan automáticamente.
🔁 Ejemplo: iterador manual en un bucle while
numeros = [10, 20, 30]
it = iter(numeros)
while True:
try:
n = next(it)
print("Número:", n)
except StopIteration:
print("Fin del iterador")
break
✅ Este patrón es útil cuando necesitas control total del flujo (por ejemplo, pausar o retomar iteraciones).
🧠 ¿Qué es un iterable y un iterador?
Término | Descripción | Ejemplo |
---|---|---|
Iterable | Objeto que puede ser recorrido (tiene __iter__() ) | Listas, tuplas, cadenas, sets, diccionarios |
Iterador | Objeto que devuelve elementos sucesivos (__next__() ) | Resultado de iter() |
lista = [1, 2, 3]
print(hasattr(lista, "__iter__")) # True → iterable
it = iter(lista)
print(hasattr(it, "__next__")) # True → iterador
🔢 2. enumerate()
: índices automáticos
Cuando necesitas tanto el índice como el valor durante un bucle, usa enumerate()
.
Es más limpio que usar range(len(...))
y evita errores de índice.
nombres = ["Ana", "Luis", "Sofía"]
for i, nombre in enumerate(nombres):
print(i, "→", nombre)
💡 enumerate()
devuelve pares (índice, elemento)
en cada iteración.
👉 Índice personalizado
for i, nombre in enumerate(nombres, start=1):
print(f"{i}. {nombre}")
📋 Salida:
1. Ana
2. Luis
3. Sofía
🧠 Ejemplo: detección con índice
letras = ["a", "b", "x", "d", "e"]
for i, letra in enumerate(letras):
if letra == "x":
print("Encontrado en posición", i)
break
✅ Ideal para búsquedas o depuración con posición.
🔗 3. zip()
: iterar en paralelo
La función zip()
combina varios iterables, devolviendo tuplas con los elementos correspondientes.
Es perfecta para recorrer listas “en paralelo”.
nombres = ["Ana", "Luis", "Sofía"]
edades = [20, 25, 22]
for nombre, edad in zip(nombres, edades):
print(nombre, "tiene", edad, "años")
💡 Salida:
Ana tiene 20 años
Luis tiene 25 años
Sofía tiene 22 años
🧮 Listas de distinta longitud
zip()
se detiene en el iterable más corto.
a = [1, 2, 3]
b = ["uno", "dos"]
for x, y in zip(a, b):
print(x, y)
📏 Salida: solo 2 pares (1-uno, 2-dos).
Para llenar los huecos, usa itertools.zip_longest()
:
from itertools import zip_longest
for x, y in zip_longest(a, b, fillvalue="(sin valor)"):
print(x, y)
💡 Salida:
1 uno
2 dos
3 (sin valor)
🧠 Ejemplo práctico: combinar datos
nombres = ["Ana", "Luis", "Sofía"]
notas = [9, 7, 10]
registro = dict(zip(nombres, notas))
print(registro)
💡 Salida: {'Ana': 9, 'Luis': 7, 'Sofía': 10}
✅ Usos comunes:
- Construir diccionarios rápidamente.
- Combinar listas relacionadas (campos y valores, claves y resultados, etc.).
- Comparar colecciones en paralelo.
⚙️ 4. Combinación: enumerate()
+ zip()
Puedes usar ambos para recorrer pares con índice incluido.
frutas = ["Manzana", "Pera", "Uva"]
colores = ["Roja", "Verde", "Morada"]
for i, (fruta, color) in enumerate(zip(frutas, colores), start=1):
print(f"{i}. {fruta} → {color}")
📋 Salida:
1. Manzana → Roja
2. Pera → Verde
3. Uva → Morada
🧠 5. Iteradores personalizados (nivel intermedio)
Además de usar los iteradores integrados, puedes crear tus propios iteradores definiendo las funciones __iter__()
y __next__()
.
class Contador:
def __init__(self, inicio, fin):
self.actual = inicio
self.fin = fin
def __iter__(self):
return self
def __next__(self):
if self.actual > self.fin:
raise StopIteration
valor = self.actual
self.actual += 1
return valor
# Uso
for n in Contador(1, 5):
print(n)
💡 Salida: 1 2 3 4 5
✅ Este patrón es útil para construir objetos que generen datos bajo demanda (p. ej., streams, generadores, lectura de archivos).
📊 Resumen visual
Función | Propósito | Devuelve | Ejemplo |
---|---|---|---|
iter() | Convierte un iterable en iterador | Iterador (control manual) | it = iter([1,2,3]) |
enumerate() | Agrega índice automático | Tuplas (índice, valor) | for i,v in enumerate(lista): |
zip() | Combina varios iterables | Tuplas de valores combinados | for a,b in zip(x, y): |
🧪 Mini-ejercicios
- Usa
iter()
ynext()
para recorrer manualmente una lista de frutas. - Recorre una lista con
enumerate()
y muestra el índice y el valor. - Combina dos listas (nombres y ciudades) usando
zip()
y crea un diccionario. - Modifica el ejercicio anterior para que muestre también el número de registro con
enumerate()
. - Crea una clase
ContadorPares
que itere solo por números pares entre dos valores.
🏁 Conclusión
Las herramientas iter()
, enumerate()
y zip()
son pilares de la iteración avanzada en Python.
Permiten recorrer datos de forma elegante, clara y eficiente, reemplazando bucles tradicionales con código más expresivo.
En la Ahora integraremos todo lo aprendido (for, while,, do while, break, continue, iter, enumerate, zip) en ejercicios prácticos y casos reales de automatización.
🏋️ Parte 6 — Ejercicios prácticos, rendimiento y resumen final
En esta última parte pondrás a prueba todo lo aprendido sobre bucles y control de iteración.
Realizaremos ejercicios integradores que combinan for
, while
, break
, continue
, zip()
, enumerate()
e incluso iter()
.
También aprenderás a escribir bucles más eficientes y a identificar cuándo simplificar el código.
🧩 Ejercicio 1 — Calculadora de notas con for
y zip()
Combina dos listas con zip()
y calcula el promedio general de los estudiantes.
nombres = ["Ana", "Luis", "Sofía"]
notas = [8.5, 9.2, 7.8]
suma = 0
for nombre, nota in zip(nombres, notas):
print(f"{nombre}: {nota}")
suma += nota
promedio = suma / len(notas)
print("Promedio general:", round(promedio, 2))
✅ Conceptos aplicados: for
, zip()
, acumulación y formato de salida.
🔁 Ejercicio 2 — Sistema de autenticación con while
y break
usuarios = {"javier": "python123", "ana": "pass2025"}
while True:
user = input("Usuario: ")
pwd = input("Contraseña: ")
if user in usuarios and usuarios[user] == pwd:
print("✅ Acceso concedido")
break
else:
print("❌ Credenciales inválidas, intenta de nuevo.")
💡 Este patrón es típico de menús y sistemas de login en consola.
📦 Ejercicio 3 — Clasificación de números (for + continue)
numeros = [15, 0, -8, 22, 13, -3]
positivos = []
negativos = []
for n in numeros:
if n == 0:
continue # omitimos el cero
if n > 0:
positivos.append(n)
else:
negativos.append(n)
print("Positivos:", positivos)
print("Negativos:", negativos)
✅ Conceptos: continue
, control de flujo, clasificación y comprensión lógica.
📊 Ejercicio 4 — Imprimir matriz con índices (enumerate()
+ anidado)
matriz = [
[10, 20, 30],
[40, 50, 60],
[70, 80, 90]
]
for i, fila in enumerate(matriz, start=1):
for j, valor in enumerate(fila, start=1):
print(f"Fila {i}, Columna {j} → {valor}")
💡 Perfecto para representar datos tabulares o manejar posiciones en matrices 2D.
⚙️ Ejercicio 5 — Contador con iter()
y next()
datos = ["Inicio", "Carga", "Procesamiento", "Fin"]
it = iter(datos)
while True:
try:
etapa = next(it)
print("→", etapa)
except StopIteration:
print("✅ Proceso completo.")
break
✅ Conceptos: iteradores manuales y control con excepciones.
🧠 Ejercicio 6 — Menú interactivo (while + match)
while True:
print("""
=== MENÚ ===
1. Mostrar saludo
2. Mostrar cuenta regresiva
3. Salir
""")
opcion = input("Elige opción: ")
match opcion:
case "1":
print("👋 ¡Hola, mundo Python!")
case "2":
for n in range(5, 0, -1):
print(n)
case "3":
print("👋 Saliendo del programa...")
break
case _:
print("❌ Opción no válida")
💡 Este patrón combina iteración + control de flujo + condiciones múltiples.
📉 Rendimiento en bucles
Python es rápido en iteraciones pequeñas, pero en colecciones grandes debes optimizar.
Aquí van algunos consejos:
- 🚀 Usa comprensiones (
[x*x for x in range(1000)]
) en lugar de bucles explícitos cuando sea posible. - 📦 Evita operaciones costosas dentro del bucle (p. ej. llamadas repetidas a funciones).
- ⚙️ Usa generadores (
(x*x for x in datos)
) para ahorrar memoria. - 💾 Precalcula valores que no cambian dentro del ciclo.
Ejemplo: diferencia de eficiencia
# 👎 Inneficiente: accede muchas veces al método len()
for i in range(len(lista)):
if len(lista) > 100:
...
# 👍 Eficiente
n = len(lista)
for i in range(n):
if n > 100:
...
📈 Ejercicio 7 — Comparación de rendimiento
Usa el módulo time
para medir dos estrategias distintas de recorrido.
import time
datos = list(range(1_000_000))
inicio = time.time()
total = 0
for n in datos:
total += n
print("FOR:", time.time() - inicio)
inicio = time.time()
total = sum(datos)
print("BUILT-IN SUM:", time.time() - inicio)
💡 Conclusión: las funciones nativas como sum()
, min()
o any()
están optimizadas en C y son más rápidas que los bucles Python puros.
🧮 Ejercicio 8 — Procesar datos con zip()
y filtrado
Supón que tienes dos listas: productos y precios.
Crea un nuevo listado solo con los productos cuyo precio supere los 10 €.
productos = ["Pan", "Leche", "Queso", "Agua"]
precios = [2, 1.5, 12, 0.9]
caros = [(p, pr) for p, pr in zip(productos, precios) if pr > 10]
print("Productos caros:")
for p, pr in caros:
print(f"- {p}: {pr} €")
✅ Combina zip()
, listas por comprensión y condición en una sola línea legible.
🧾 Autoevaluación final
- ✅ Entiendo cómo y cuándo usar
for
ywhile
. - ✅ Puedo usar
break
,continue
ypass
para controlar el flujo. - ✅ Sé trabajar con bucles anidados.
- ✅ Sé aplicar
enumerate()
,zip()
eiter()
correctamente. - ✅ Conozco cómo escribir bucles eficientes y legibles.
📚 Resumen visual
Tema | Resumen | Ejemplo |
---|---|---|
for | Recorre secuencias o colecciones | for x in lista: |
while | Repite mientras se cumpla una condición | while x < 10: |
break | Rompe el bucle actual | if x == 5: break |
continue | Salta a la siguiente iteración | if x % 2 == 0: continue |
zip() | Combina listas en paralelo | for a,b in zip(x,y): |
enumerate() | Añade índices automáticos | for i,v in enumerate(lista): |
iter() | Crea iteradores manuales | it = iter(lista) |
💬 Reflexión final
Dominar las estructuras de iteración es dominar el pulso lógico del programa.
Los bucles son la esencia de toda automatización: repiten, filtran, procesan y generan resultados.
La clave está en mantener claridad y eficiencia:
- Menos líneas ≠ mejor código; legibilidad primero.
- Aprende a usar funciones nativas y comprensión de listas para simplificar tareas.
- Optimiza los bucles grandes con generadores e iteradores.
➡️ En la próxima lección entrarás en el tema Funciones y Manejo de Excepciones y errores,
donde aprenderás a encapsular código repetitivo dentro de bloques reutilizables, llevando tu dominio de Python al siguiente nivel.