Estructuras iterativas
Las estructuras de control iterativas, de repetición o bucles, facilitan la repetición de un bloque de instrucciones un número determinado de veces o mientras se cumpla una condición.
En Python, y en la mayoría de lenguajes, existen dos tipos de estructuras iterativas: for y while. En los siguientes apartados veremos primero la sentencia for, después la sentencia while y, por último, las sentencias de salto (break, continue) que se pueden usar con ambas.
La sentencia for
Un bucle for sirve para recorrer, uno a uno, los elementos de una secuencia (por ejemplo, los caracteres de una cadena de texto, o una serie de números generada con range()), ejecutando el cuerpo del bucle una vez por cada elemento. A diferencia del while, no hace falta declarar ni actualizar manualmente una variable de control: for se encarga de ir avanzando por la secuencia automáticamente.
Recorrer una cadena de texto
for letra in "Python":
print(letra)
letra es una variable que, en cada vuelta del bucle, toma el valor del siguiente carácter de la cadena "Python": primero "P", luego "y", luego "t"... hasta llegar al último carácter. El bucle termina automáticamente cuando ya no quedan caracteres, sin que tengas que comprobar tú ninguna condición.
La función range()
Cuando lo que quieres es repetir algo un número determinado de veces (en lugar de recorrer los caracteres de una cadena), puedes usar la función interna range(), que genera una secuencia de números enteros:
for i in range(5):
print(i)
# 0
# 1
# 2
# 3
# 4
range(5) genera los números del 0 al 4 (cinco valores en total, sin incluir el 5). range() admite hasta tres argumentos:
range(fin) # de 0 a fin-1
range(inicio, fin) # de inicio a fin-1
range(inicio, fin, paso) # de inicio a fin-1, avanzando de "paso" en "paso"
for i in range(2, 10, 2):
print(i)
# 2
# 4
# 6
# 8
La función enumerate()
A veces, mientras recorres una secuencia, también necesitas saber en qué posición (índice) va cada elemento. Para eso existe enumerate(), que combina cada elemento con su posición:
for indice, letra in enumerate("Python"):
print(indice, letra)
# 0 P
# 1 y
# 2 t
# 3 h
# 4 o
# 5 n
En cada vuelta del bucle, indice toma el valor de la posición (empezando en 0) y letra el elemento que ocupa esa posición.
Por defecto, enumerate() siempre empieza a contar en 0. Si quieres que la numeración empiece en otro valor (por ejemplo, en 1), puedes indicarlo con su segundo argumento, start:
for indice, letra in enumerate("Python", start=1):
print(indice, letra)
# 1 P
# 2 y
# 3 t
# 4 h
# 5 o
# 6 n
letra sigue recorriendo los mismos caracteres que antes; lo único que cambia es el punto de partida de indice.
for o while?Usa for cuando sepas de antemano qué vas a recorrer (una cadena, un rango de números...). Usa while cuando el número de repeticiones dependa de una condición que solo se puede comprobar en tiempo de ejecución (por ejemplo, repetir hasta que el usuario introduzca un valor válido).
Actualización de variables
Uno de los usos habituales de sentencias de asignación consiste en realizar una actualización sobre una variable, en la que el valor nuevo de esa variable depende del antiguo.
x = x + 1
Esto quiere decir: toma el valor actual de x, añádele 1, y luego actualiza x con el nuevo valor.
Si intentas actualizar una variable que no existe, obtendrás un error, ya que Python evalúa el lado derecho antes de asignar el valor a x.
x = x + 1 # NameError: name 'x' is not defined
Antes de que puedas actualizar una variable, debes inicializarla, generalmente mediante una asignación.
x = 0
x = x + 1
Actualizar una variable añadiéndole 1 se llama incrementar; restarle 1 recibe el nombre de decrementar.
La sentencia while
Los ordenadores se utilizan a menudo para automatizar tareas repetitivas. Repetir tareas idénticas o muy similares sin cometer errores es algo que a las máquinas se les da bien y en cambio a las personas no. Como las iteraciones resultan tan habituales, Python proporciona varias características en su lenguaje para hacerlas sencillas.
Una forma de iteración en Python es la sentencia while.
Aquí un programa sencillo que cuenta hacia atrás desde cinco y luego dice ¡Despegue!.
n = 5
while n > 0:
print(n)
n = n - 1
print('¡Despegue!')
Casi se puede leer la sentencia while como si estuviera en inglés. Significado: mientras n sea mayor que 0, muestra el valor de n y luego reduce el valor de n en una unidad. Cuando llegues a 0, sal de la sentencia while y muestra la palabra "¡Despegue!".
Este es el flujo de ejecución de la sentencia while, explicado de un modo más formal.
- Se evalúa la condición, obteniendo
TrueoFalse. - Si la condición es falsa, se sale de la sentencia
whiley se continúa la ejecución en la siguiente sentencia. - Si la condición es verdadera, se ejecuta el cuerpo del
whiley luego se vuelve al paso 1.
Este tipo de flujo recibe el nombre de bucle, ya que el tercer paso enlaza de nuevo con el primero. Cada vez que se ejecuta el cuerpo del bucle se dice que realizamos una iteración. Para el bucle anterior, podríamos decir que tuvo cinco iteraciones, lo que significa que el cuerpo del bucle se ejecutó cinco veces.
El cuerpo del bucle debe cambiar el valor de una o más variables, de manera que la condición pueda en algún momento evaluarse como falsa y el bucle termine. La variable que cambia cada vez que el bucle se ejecuta y controla cuándo termina este, recibe el nombre de variable de iteración. Si no hay variable de iteración, el bucle se repetirá para siempre, resultando así en un bucle infinito.
Variables acumuladoras
Las variables acumuladoras son variables que se usan para mantener y acumular una suma o total de valores durante la ejecución de un bucle. Estas variables son útiles cuando necesitas realizar cálculos iterativos que requieren la acumulación de resultados parciales en cada iteración del bucle.
Las características de las variables acumuladoras son:
- Inicialización: Normalmente, las variables acumuladoras se inicializan con un valor inicial antes de comenzar el bucle. El valor inicial depende del tipo de acumulación que se desea realizar.
- Para acumular sumas, la variable acumuladora se inicializa en
0. - Para acumular producto, la variable acumuladora se inicializa en
1.
- Para acumular sumas, la variable acumuladora se inicializa en
- Actualización: Durante cada iteración del bucle, la variable acumuladora se actualiza usando la operación que corresponde al cálculo que se está realizando. Por ejemplo, si estás sumando números, agregarás el valor actual a la variable acumuladora en cada iteración.
- Uso después del bucle: Una vez que el bucle termina, la variable acumuladora contiene el resultado final de la acumulación, que puede ser usado para otras operaciones o para la salida del programa.
Ejemplo:
# Número hasta el que se va a sumar
n = 10
# Inicialización de la variable acumuladora
suma = 0
# Inicialización del contador
contador = 1
# Bucle while para sumar los números de 1 a n
while contador <= n:
suma += contador # Actualización de la variable acumuladora
contador += 1 # Incremento del contador
# Mostrar el resultado
print("La suma total es:", suma)
Ejemplo: Lector de números
Escribe un programa que lea repetidamente números hasta que el usuario introduzca la palabra "fin". Una vez introducido, muestra en pantalla el total, la cantidad de números y la suma de esos números.
Solución 1
# Inicializamos las variables
numero_variables = 0
suma_total = 0
# Creamos una bandera para saber cuándo salir del bucle
flag = True
while flag:
# Leemos los datos del usuario
palabra = input("Introduce un numero:")
# Si el usuario introduce fin, ponemos la bandera a falso para salir del bucle
if palabra == 'fin':
flag = False
# Si no, seguimos procesando el dato que introdujo el usuario
else:
numero = int(palabra)
# Vamos guardando el número de variables y la suma total
numero_variables = numero_variables + 1
suma_total = suma_total + numero
# Se muestra en pantalla la solución
print("Números introducidos:", numero_variables)
print("Suma de números:", suma_total)
Solución 2
# Inicializamos las variables
numero_variables = 0
suma_total = 0
# Solo salimos del bucle si se ejecuta un break
while True:
# Leemos los datos del usuario
palabra = input("Introduce un numero:")
# Si el usuario introduce fin, salimos del bucle con break
if palabra == 'fin':
break
numero = int(palabra)
# Vamos guardando el número de variables y la suma total
numero_variables = numero_variables + 1
suma_total = suma_total + numero
# Se muestra en pantalla la solución
print("Números introducidos:", numero_variables)
print("Suma de números:", suma_total)
Sentencias de salto
Dentro de un bucle, Python ofrece dos sentencias para alterar su flujo normal de ejecución: break, que lo interrumpe por completo, y continue, que salta a la siguiente iteración sin ejecutar el resto del cuerpo del bucle.
Además, tanto for como while admiten una cláusula else poco conocida pero útil: se ejecuta cuando el bucle termina sin haberse interrumpido con break.
Bucles infinitos y break
A veces no se sabe si hay que terminar un bucle hasta que se ha recorrido la mitad del cuerpo del mismo. En ese caso se puede crear un bucle infinito a propósito y usar la sentencia break para salir de él cuando se desee.
El bucle siguiente es, obviamente, un bucle infinito, porque la expresión lógica de la sentencia while siempre es verdadera.
n = 10
while True:
print(n, end=' ')
n = n - 1
print('¡Terminado!')
Si cometes el error de ejecutar este código, aprenderás rápidamente cómo detener un proceso de Python bloqueado por el sistema, o tendrás que localizar dónde se encuentra el botón de apagado de tu equipo. Este programa funcionará para siempre, o hasta que la batería del equipo se agote, ya que la expresión lógica al principio del bucle siempre es verdadera.
A pesar de que este es un caso de bucle infinito inútil, se puede usar ese diseño para construir bucles útiles, siempre que se tenga precaución de añadir código en el cuerpo del bucle para salir explícitamente, usando break cuando se alcance la condición de salida.
Por ejemplo, supón que quieres recoger entradas de texto de usuario hasta que escriba fin. Podrías escribir:
while True:
linea = input("> ")
if linea == "fin":
break
print(linea)
print("¡Terminado!")
La condición del bucle es True, lo cual es verdadero siempre, así que el bucle se repetirá hasta que se ejecute la sentencia break.
Cada vez que se entra en el bucle, se le pide texto al usuario. Si el usuario escribe fin, la sentencia break hará que se salga del bucle. En cualquier otro caso, el programa repetirá cualquier cosa que el usuario escriba y volverá al principio del bucle. Este es un ejemplo de su funcionamiento:
> hola a todos
hola a todos
> terminé
terminé
> fin
¡Terminado!
Finalizar interaciones con continue
Algunas veces, estando dentro de un bucle se necesita terminar la iteración actual y saltar a la siguiente de manera inmediata. En este caso puedes utilizar la sentencia continue para pasar a la siguiente iteración sin terminar la ejecución del cuerpo del bucle para la actual.
A continuación se muestra un ejemplo de un bucle que repite lo que recibe como entrada hasta que el usuario escribe fin, pero trata las líneas que empiezan por el carácter # como líneas que no deben mostrarse en pantalla.
while True:
linea = input("> ")
if linea[0] == '#' :
continue
if linea == 'fin':
break
print(linea)
print('¡Terminado!')
Aquí una ejecución de ejemplo de ese nuevo programa con la sentencia continue añadida.
> hola a todos
hola a todos
> # no imprimas esto
> ¡imprime esto!
¡imprime esto!
> fin
¡Terminado!
Todas las líneas se imprimen en pantalla, excepto la que comienza con el símbolo #, ya que en ese caso se ejecuta continue, finaliza la iteración actual y salta de vuelta a la sentencia while para comenzar la siguiente iteración, de modo que se omite la sentencia print.
Cláusula else de los bucles
Tanto for como while pueden llevar un bloque else a continuación. Ese bloque se ejecuta una única vez, cuando el bucle termina de forma normal, es decir, sin haber sido interrumpido por un break.
for n in range(1, 6):
if n % 2 == 0:
print(f"Encontrado un número par: {n}")
break
else:
print("No hay ningún número par en el rango")
Si el break se ejecuta, el bloque else se salta. Si el bucle recorre todos los elementos (o, en un while, la condición se vuelve falsa) sin que se llegue a ejecutar ningún break, el bloque else sí se ejecuta.
Es especialmente útil para expresar patrones de búsqueda: "recorre esta colección y, si no encuentras lo que buscas, haz esto otro".
password = input("Introduce la contraseña: ")
intentos = 0
while intentos < 3:
if password == "1234":
print("Acceso correcto")
break
password = input("Contraseña incorrecta. Inténtalo de nuevo: ")
intentos += 1
else:
print("Demasiados intentos fallidos")