12. Iteración con bucles for y range()
En el Capítulo 11, aprendimos sobre los bucles while, que repiten acciones mientras una condición se mantenga verdadera. Aunque los bucles while son potentes y flexibles, requieren que gestionemos manualmente contadores de bucle y actualicemos condiciones. Python proporciona otro tipo de bucle: el bucle for—que destaca en una tarea diferente pero extremadamente común: procesar cada elemento de una colección de datos, uno a la vez.
El bucle for es una de las características más utilizadas de Python. Ya sea que estés procesando líneas en un archivo, calculando estadísticas a partir de una secuencia de números o comprobando cada carácter de una cadena, el bucle for ofrece una forma limpia y legible de trabajar con secuencias de datos. En este capítulo, exploraremos cómo funcionan los bucles for, cómo usar la función range() de Python para operaciones de conteo, y cómo controlar la ejecución del bucle con break, continue y la cláusula else, menos conocida.
12.1) El bucle for y los conceptos de iteración
12.1.1) ¿Qué es un bucle for?
Un bucle for en Python repite un bloque de código una vez por cada elemento de una secuencia. La secuencia podría ser una cadena, una lista (que aprenderemos en detalle en el Capítulo 14), o cualquier otra colección de elementos. La diferencia clave respecto a un bucle while es que un bucle for gestiona automáticamente la iteración: no necesitas actualizar manualmente un contador ni comprobar una condición.
Esta es la estructura básica de un bucle for:
for variable in sequence:
# Bloque de código que se ejecuta para cada elemento
# La variable contiene el elemento actualEl bucle for funciona así:
- Python toma el primer elemento de la secuencia y lo asigna a la variable
- Se ejecuta el bloque de código (con sangría debajo de la sentencia
for) - Python toma el siguiente elemento, lo asigna a la variable y vuelve a ejecutar el bloque
- Esto continúa hasta que todos los elementos de la secuencia han sido procesados
Veamos un ejemplo simple con una cadena:
# Imprimir cada carácter de un nombre
name = "Alice"
for character in name:
print(character)Output:
A
l
i
c
eEn este ejemplo, la cadena "Alice" es la secuencia. El bucle procesa cada carácter de uno en uno. Durante la primera iteración, character contiene 'A', durante la segunda iteración contiene 'l', y así sucesivamente. El nombre de la variable character es una elección nuestra: podríamos haberla llamado letter, char o incluso simplemente c. Elige nombres que dejen claro el propósito de tu código.
Convenciones de nombres para variables de bucle: Al escribir bucles for, elige nombres de variables que describan lo que representa cada elemento. Usa nombres descriptivos como character, student o score cuando el valor sea importante para comprender tu código. Usa i para contadores numéricos simples cuando solo estés contando iteraciones. Usa _ (guion bajo) cuando no necesites el valor en absoluto; esta es una convención de Python que significa "no me importa este valor".
Aquí tienes un ejemplo práctico que cuenta vocales en una palabra:
# Contar vocales en una palabra
word = "Python"
vowel_count = 0
for letter in word:
if letter in "aeiouAEIOU":
vowel_count += 1
print(f"Found vowel: {letter}")
print(f"Total vowels: {vowel_count}")Output:
Found vowel: o
Total vowels: 1El bucle examina cada letra en "Python". Cuando encuentra una vocal (usando el operador in que aprendimos en el Capítulo 7), incrementa el contador e imprime un mensaje. Este patrón—inicializar un contador antes del bucle y luego actualizarlo dentro—es extremadamente común en programación.
Aquí tienes otro ejemplo que demuestra la acumulación construyendo un resultado:
# Contar letras en mayúscula en una cadena
text = "Python Programming"
uppercase_count = 0
for char in text:
if char.isupper():
uppercase_count += 1
print(f"Found {uppercase_count} uppercase letters in '{text}'")Output:
Found 2 uppercase letters in 'Python Programming'Este ejemplo muestra el patrón de acumulación: inicializamos un contador en cero antes del bucle, luego examinamos cada carácter e incrementamos el contador cuando encontramos una letra en mayúscula. Después de que el bucle termina, usamos el resultado acumulado. Este patrón aparece constantemente en programación: contar elementos que cumplen ciertos criterios, sumar valores o ir construyendo resultados paso a paso.
12.1.2) Comprender la iteración
La iteración es el proceso de repetir una acción para cada elemento de una colección. Cuando decimos que un objeto es iterable, queremos decir que Python puede procesar sus elementos uno a la vez en un bucle for. Las cadenas son iterables: podemos recorrer sus caracteres. Como veremos en breve, muchos otros tipos de Python también son iterables.
La variable en un bucle for (como character o letter en nuestros ejemplos) se llama la variable de bucle. Esta variable es creada automáticamente por el bucle for y existe solo dentro del ámbito del bucle. Cada vez que se recorre el bucle, Python asigna el siguiente elemento de la secuencia a esta variable.
Aquí tienes un ejemplo que demuestra cómo cambia la variable de bucle:
# Mostrar cómo se actualiza la variable de bucle
colors = "RGB" # Rojo, Verde, Azul
for color_code in colors:
print(f"Processing color code: {color_code}")
print(f" This is iteration for '{color_code}'")Output:
Processing color code: R
This is iteration for 'R'
Processing color code: G
This is iteration for 'G'
Processing color code: B
This is iteration for 'B'Cada vez que se recorre el bucle, color_code contiene un carácter diferente de la cadena. El bucle avanza automáticamente al siguiente carácter: no necesitamos escribir ningún código para avanzar por la secuencia.
12.1.3) El bucle for vs el bucle while para iteración
Podríamos lograr el mismo procesamiento carácter por carácter con un bucle while, pero requiere más código y gestión manual:
# Usar un bucle while para iterar sobre una cadena (más complejo)
name = "Alice"
index = 0
while index < len(name):
character = name[index]
print(character)
index += 1 # Debes actualizar manualmente el índiceEsto produce la misma salida que nuestro ejemplo anterior con for, pero fíjate en lo que tuvimos que hacer:
- Crear e inicializar una variable de índice
- Comprobar la condición
index < len(name)en cada iteración - Extraer manualmente el carácter usando
name[index] - Recordar incrementar el índice (¡olvidarlo crea un bucle infinito!)
El bucle for gestiona todo esto automáticamente:
# Usar un bucle for para iterar sobre una cadena (más simple)
name = "Alice"
for character in name:
print(character)Esto es mucho más limpio y menos propenso a errores. El bucle for es la opción natural cuando quieres procesar cada elemento de una colección. Usa un bucle while cuando necesites más control sobre la lógica de iteración o cuando no sepas de antemano cuántas veces hay que repetir.
12.2) Usar range() para bucles de conteo
12.2.1) Introducir la función range()
Mientras que los bucles for destacan al procesar secuencias existentes, a menudo necesitamos repetir una acción un número específico de veces, como imprimir un mensaje cinco veces o calcular los primeros diez números cuadrados. La función range() de Python genera una secuencia de números sobre la que podemos iterar con un bucle for.
La forma más simple de range() toma un argumento: el número de enteros a generar, empezando desde 0:
# Imprimir números del 0 al 4
for number in range(5):
print(number)Output:
0
1
2
3
4⚠️ Error común: Los principiantes a menudo esperan que range(5) produzca 1, 2, 3, 4, 5, pero en realidad produce 0, 1, 2, 3, 4. Recuerda: range(n) empieza en 0 y se detiene antes de n. Este comportamiento de "detenerse antes" es coherente con el slicing de Python, que aprendimos en el Capítulo 5. El rango empieza en 0 (por defecto) y llega hasta, pero sin incluir, el valor de parada.
Este patrón es perfecto para repetir una acción un número específico de veces:
# Imprimir un saludo cinco veces
for i in range(5):
print(f"Welcome! (iteration {i})")Output:
Welcome! (iteration 0)
Welcome! (iteration 1)
Welcome! (iteration 2)
Welcome! (iteration 3)
Welcome! (iteration 4)La variable i es un nombre común para un contador de bucle (abreviatura de "index" o "iteration"), aunque puedes usar cualquier nombre de variable válido. Cuando el valor de la variable del bucle no importa para tu lógica, i es una elección convencional.
12.2.2) Especificar valores de inicio y fin
Puedes proporcionar dos argumentos a range() para especificar tanto dónde empezar como dónde detenerse:
# Imprimir números del 1 al 5
for number in range(1, 6):
print(number)Output:
1
2
3
4
5Aquí, range(1, 6) empieza en 1 y se detiene antes de 6, dándonos los números del 1 al 5. Esto es útil cuando necesitas contar a partir de un valor distinto de cero.
Usemos esto para calcular una tabla de multiplicar simple:
# Imprimir la tabla del 7 del 1 al 10
multiplier = 7
for number in range(1, 11):
result = multiplier * number
print(f"{multiplier} × {number} = {result}")Output:
7 × 1 = 7
7 × 2 = 14
7 × 3 = 21
7 × 4 = 28
7 × 5 = 35
7 × 6 = 42
7 × 7 = 49
7 × 8 = 56
7 × 9 = 63
7 × 10 = 70El bucle se ejecuta de 1 a 10, multiplicando cada número por 7. Esto demuestra cómo range() facilita realizar cálculos sobre una secuencia numérica específica.
12.2.3) Usar un valor de paso
La función range() acepta un tercer argumento opcional: el valor de paso (step), que determina cuánto aumentar (o disminuir) entre números:
# Imprimir números pares del 0 al 10
for number in range(0, 11, 2):
print(number)Output:
0
2
4
6
8
10Con range(0, 11, 2), empezamos en 0, nos detenemos antes de 11 y aumentamos en 2 cada vez. Esto nos da todos los números pares del 0 al 10.
También puedes usar un paso negativo para contar hacia atrás:
# Cuenta atrás del 10 al 1
for number in range(10, 0, -1):
print(number)
print("Liftoff!")Output:
10
9
8
7
6
5
4
3
2
1
Liftoff!Aquí, range(10, 0, -1) empieza en 10, se detiene antes de 0 y disminuye en 1 cada vez. El paso negativo hace que el rango cuente hacia atrás.
Veamos un ejemplo práctico que calcula la suma de todos los números impares del 1 al 100:
# Sumar todos los números impares del 1 al 100
total = 0
for number in range(1, 101, 2): # Empezar en 1, paso de 2
total += number
print(f"Sum of odd numbers from 1 to 100: {total}")Output:
Sum of odd numbers from 1 to 100: 2500Al usar range(1, 101, 2), generamos solo los números impares (1, 3, 5, ..., 99), evitando la necesidad de comprobar la paridad de cada número dentro del bucle. Esto hace que el código sea más eficiente y que su intención quede más clara.
12.2.4) Qué devuelve realmente range()
La función range() no crea una lista de números en memoria: crea un objeto range (range object) que genera números bajo demanda. Esto es eficiente en memoria, especialmente para rangos grandes:
# range() devuelve un objeto range, no una lista
numbers = range(1000000)
print(type(numbers)) # Output: <class 'range'>
print(numbers) # Output: range(0, 1000000)Output:
<class 'range'>
range(0, 1000000)Aunque este rango representa un millón de números, usa muy poca memoria porque Python no crea realmente los millón de números hasta que iteras sobre ellos. Cada número se genera solo cuando el bucle lo necesita.
Si necesitas una lista real de números, puedes convertir el rango:
# Convertir range a una lista
small_numbers = list(range(5))
print(small_numbers) # Output: [0, 1, 2, 3, 4]Output:
[0, 1, 2, 3, 4]Aprenderemos más sobre las listas y la función list() en el Capítulo 14. Por ahora, solo sabe que range() funciona perfectamente con bucles for sin ninguna conversión.
12.3) Iterar sobre cadenas y otras secuencias
12.3.1) Iterar sobre cadenas carácter por carácter
Ya hemos visto varios ejemplos de iterar sobre cadenas. Este es uno de los usos más comunes de los bucles for porque las cadenas son secuencias de caracteres, y a menudo necesitamos examinar o procesar cada carácter de forma individual.
Aquí tienes un ejemplo que valida una contraseña comprobando que contiene al menos un dígito:
# Comprobar si una contraseña contiene al menos un dígito
password = "secure123"
has_digit = False
for character in password:
if character.isdigit():
has_digit = True
print(f"Found digit: {character}")
if has_digit:
print("Password contains at least one digit ✓")
else:
print("Password must contain at least one digit ✗")Output:
Found digit: 1
Found digit: 2
Found digit: 3
Password contains at least one digit ✓El bucle examina cada carácter usando el método de cadena .isdigit() (que aprendimos en el Capítulo 5). Cuando encuentra un dígito, establece has_digit en True. Después de que el bucle termina, comprobamos la bandera para determinar si se encontró algún dígito.
Aquí tienes otro ejemplo práctico que cuenta diferentes tipos de caracteres:
# Analizar tipos de caracteres en una cadena
text = "Hello, World! 123"
letters = 0
digits = 0
spaces = 0
other = 0
for char in text:
if char.isalpha():
letters += 1
elif char.isdigit():
digits += 1
elif char.isspace():
spaces += 1
else:
other += 1
print(f"Letters: {letters}")
print(f"Digits: {digits}")
print(f"Spaces: {spaces}")
print(f"Other: {other}")Output:
Letters: 10
Digits: 3
Spaces: 2
Other: 2Este bucle clasifica cada carácter usando métodos de cadena que aprendimos en el Capítulo 5. La cadena if-elif-else (del Capítulo 8) asegura que cada carácter se cuente en exactamente una categoría.
12.3.2) Procesar cadenas con índices
A veces necesitas tanto el carácter como su posición en la cadena. Puedes usar range(len(string)) para iterar sobre los índices:
# Encontrar posiciones de un carácter específico
text = "Mississippi"
search_char = "s"
print(f"Looking for '{search_char}' in '{text}':")
for index in range(len(text)):
if text[index] == search_char:
print(f" Found at index {index}")Output:
Looking for 's' in 'Mississippi':
Found at index 2
Found at index 3
Found at index 5
Found at index 6El bucle itera sobre índices desde 0 hasta len(text) - 1. Para cada índice, comprobamos si el carácter en esa posición coincide con nuestro carácter de búsqueda. Este enfoque es útil cuando necesitas saber dónde aparece algo, no solo que aparece.
12.3.3) Iterar sobre otros tipos de secuencia
El bucle for funciona con cualquier secuencia iterable en Python. Aunque en este capítulo nos hemos centrado en las cadenas, aprenderás sobre otros tipos de secuencia en capítulos posteriores. Por ejemplo, el Capítulo 14 te enseñará sobre las listas, que son colecciones ordenadas que pueden contener múltiples valores de cualquier tipo. La sintaxis del bucle for sigue siendo la misma independientemente del tipo de secuencia sobre la que estés iterando: el bucle gestiona automáticamente obtener cada elemento de la secuencia.
12.4) Usar break y continue en bucles for
12.4.1) La sentencia break en bucles for
Al igual que con los bucles while (Capítulo 11), la sentencia break sale inmediatamente de un bucle for, omitiendo cualquier iteración restante. Esto es útil cuando has encontrado lo que buscas y no necesitas seguir buscando.
Aquí tienes un ejemplo que busca un carácter específico:
# Buscar la primera vocal en una cadena
text = "Python"
found_vowel = False
for char in text:
if char.lower() in "aeiou":
print(f"First vowel found: {char}")
found_vowel = True
break # Dejar de buscar una vez que encontramos la primera vocal
if not found_vowel:
print("No vowels found")Output:
First vowel found: oSin break, el bucle seguiría examinando todos los caracteres restantes incluso después de encontrar la primera vocal. La sentencia break hace que el código sea más eficiente al detenerse tan pronto como la tarea se completa.
Aquí tienes un ejemplo práctico que valida la entrada del usuario comprobando caracteres no válidos:
# Comprobar si un nombre de usuario contiene solo caracteres permitidos
username = "alice_123"
allowed = "abcdefghijklmnopqrstuvwxyz0123456789_"
is_valid = True
for char in username:
if char.lower() not in allowed:
print(f"Invalid character found: '{char}'")
is_valid = False
break # No hace falta comprobar más
if is_valid:
print(f"Username '{username}' is valid ✓")
else:
print(f"Username '{username}' is invalid ✗")Output:
Username 'alice_123' is valid ✓El bucle comprueba cada carácter contra el conjunto permitido. Si encuentra un carácter no válido, informa del problema y sale del bucle inmediatamente: no tiene sentido comprobar el resto del nombre de usuario una vez que sabemos que no es válido.
12.4.2) La sentencia continue en bucles for
La sentencia continue omite el resto de la iteración actual y pasa al siguiente elemento de la secuencia. Esto es útil cuando quieres omitir ciertos elementos sin salir del bucle por completo.
Aquí tienes un ejemplo que procesa solo ciertos caracteres:
# Imprimir solo consonantes de una cadena
word = "Programming"
for letter in word:
if letter.lower() in "aeiou":
continue # Omitir vocales
print(letter, end="")
print() # Nueva línea al finalOutput:
PrgrmmngCuando el bucle encuentra una vocal, continue omite la sentencia print() y pasa al siguiente carácter. Solo las consonantes llegan a la sentencia de impresión.
Aquí tienes un ejemplo más práctico que calcula estadísticas mientras omite datos no válidos. Observa que el método .split() (del Capítulo 6) devuelve una lista de cadenas, que aprenderemos en el Capítulo 14. Por ahora, solo sabe que los bucles for pueden iterar sobre el resultado:
# Calcular el promedio de puntuaciones válidas de un examen (0-100)
# El método .split() devuelve una lista de cadenas (Capítulo 14)
scores_input = "85 92 -5 78 105 90 88"
valid_scores = 0
total = 0
for score_str in scores_input.split():
score = int(score_str)
if score < 0 or score > 100:
print(f"Skipping invalid score: {score}")
continue # Omitir esta puntuación
valid_scores += 1
total += score
if valid_scores > 0:
average = total / valid_scores
print(f"Average of {valid_scores} valid scores: {average:.1f}")
else:
print("No valid scores to average")Output:
Skipping invalid score: -5
Skipping invalid score: 105
Average of 5 valid scores: 86.6El bucle procesa cada cadena de puntuación. Cuando encuentra una puntuación no válida (negativa o mayor que 100), imprime una advertencia y usa continue para omitir añadir esa puntuación al total. Esto permite que el bucle procese todas las puntuaciones válidas mientras ignora las no válidas.
12.4.3) Cuándo usar break y continue
Usa break cuando:
- Estás buscando algo y quieres detenerte una vez que lo encuentres
- Has encontrado una condición de error que hace que continuar no tenga sentido
- Has completado tu tarea y no necesitas procesar los elementos restantes
Usa continue cuando:
- Quieres omitir ciertos elementos según una condición
- Estás filtrando datos y quieres procesar solo elementos que cumplan criterios
- Quieres evitar sentencias
ifprofundamente anidadas manejando casos especiales pronto
Tanto break como continue pueden hacer tu código más claro al mostrar explícitamente cuándo y por qué estás cambiando el flujo normal de la iteración. Sin embargo, abusar de ellos puede hacer que el código sea más difícil de seguir: úsalos cuando realmente mejoren la claridad.
12.5) Usar else con bucles for
12.5.1) El patrón for-else
Los bucles for de Python admiten una cláusula else opcional que se ejecuta después de que el bucle termina normalmente; es decir, cuando el bucle termina de iterar por todos los elementos sin encontrar una sentencia break. Esto puede parecer extraño al principio (¿por qué "else" si no hay "if"?), pero es útil para distinguir entre "encontré lo que buscaba" y "busqué en todo y no lo encontré".
Esta es la estructura básica:
for item in sequence:
# Cuerpo del bucle
if some_condition:
break
else:
# Esto se ejecuta solo si el bucle terminó sin hacer break
print("Loop completed normally")El bloque else se ejecuta si y solo si el bucle sale de forma natural al agotar la secuencia. Si una sentencia break sale del bucle antes de tiempo, el bloque else se omite.
Veamos un ejemplo práctico que busca un valor específico. El método .split() (del Capítulo 6) devuelve una lista de cadenas, que aprenderemos en el Capítulo 14:
# Buscar un número objetivo
numbers = "2 4 6 8 10"
target = 7
for num_str in numbers.split():
num = int(num_str)
if num == target:
print(f"Found {target}!")
break
else:
print(f"{target} not found in the sequence")Output:
7 not found in the sequenceEl bucle busca en todos los números. Como nunca encuentra 7, termina normalmente y se ejecuta el bloque else. Ahora busquemos un número que sí existe:
# Buscar un número objetivo que existe
numbers = "2 4 6 8 10"
target = 6
for num_str in numbers.split():
num = int(num_str)
if num == target:
print(f"Found {target}!")
break
else:
print(f"{target} not found in the sequence")Output:
Found 6!Esta vez, cuando el bucle encuentra 6, ejecuta break, lo que omite por completo el bloque else. Este patrón maneja elegantemente tanto el caso "encontrado" como el caso "no encontrado" sin necesitar una variable bandera separada.
12.5.2) Usos prácticos de for-else
El patrón for-else es especialmente útil para operaciones de búsqueda. Aquí tienes un ejemplo que valida si una cadena contiene solo dígitos:
# Comprobar si una cadena es un entero válido
user_input = "12345"
for char in user_input:
if not char.isdigit():
print(f"Invalid: '{char}' is not a digit")
break
else:
print(f"'{user_input}' is a valid integer")Output:
'12345' is a valid integerSi la entrada contiene cualquier carácter que no sea un dígito, el bucle hace break y el bloque else no se ejecuta. Si todos los caracteres son dígitos, el bucle termina normalmente y el bloque else confirma la validez.
Probemos con una entrada no válida:
# Comprobar si una cadena es un entero válido (caso no válido)
user_input = "123a5"
for char in user_input:
if not char.isdigit():
print(f"Invalid: '{char}' is not a digit")
break
else:
print(f"'{user_input}' is a valid integer")Output:
Invalid: 'a' is not a digit12.5.3) Comparar for-else con variables bandera
Antes de aprender sobre for-else, quizá usabas una variable bandera para rastrear si se encontró algo:
# Usar una variable bandera (enfoque tradicional)
text = "Python"
found_vowel = False
for char in text:
if char.lower() in "aeiou":
print(f"Found vowel: {char}")
found_vowel = True
break
if not found_vowel:
print("No vowels found")Output:
Found vowel: oEl patrón for-else elimina la necesidad de la variable bandera:
# Usar for-else (más Pythonic)
text = "Python"
for char in text:
if char.lower() in "aeiou":
print(f"Found vowel: {char}")
break
else:
print("No vowels found")Output:
Found vowel: oAmbos enfoques funcionan correctamente, pero la versión con for-else es más concisa y expresa claramente la intención: "busca algo, y si no lo encuentras, haz esto". La cláusula else representa directamente el caso de "no encontrado".
12.6) Elegir entre bucles for y while
12.6.1) Cuándo usar un bucle for
Usa un bucle for cuando:
1. Estás procesando cada elemento en una colección:
# Procesar cada carácter en una cadena
message = "Hello"
for char in message:
print(char.upper())Output:
H
E
L
L
O2. Necesitas repetir una acción un número específico de veces:
# Imprimir una línea de borde
for i in range(40):
print("-", end="")
print()Output:
----------------------------------------3. Estás iterando sobre un rango numérico:
# Calcular el factorial de 5
factorial = 1
for n in range(1, 6):
factorial *= n
print(f"5! = {factorial}")Output:
5! = 1204. Sabes de antemano sobre qué estás iterando:
# Procesar una secuencia conocida de valores
grades = "A B C D F"
for grade in grades.split():
print(f"Grade: {grade}")Output:
Grade: A
Grade: B
Grade: C
Grade: D
Grade: FLa característica clave de los bucles for es que funcionan con iteración definida (definite iteration): sabes qué secuencia estás recorriendo, incluso si no sabes de antemano cuántos elementos contiene.
12.6.2) Cuándo usar un bucle while
Usa un bucle while cuando:
1. Estás repitiendo hasta que una condición cambie:
# Seguir preguntando hasta recibir una entrada válida
while True:
age_input = input("Enter your age: ")
if age_input.isdigit():
age = int(age_input)
if age > 0:
print(f"Age recorded: {age}")
break
print("Please enter a valid positive number")2. No sabes cuántas iteraciones necesitarás:
# Contar cuántas veces puedes duplicar un número antes de superar 1000
number = 1
count = 0
while number <= 1000:
number *= 2
count += 1
print(f"Doubled {count} times to reach {number}")Output:
Doubled 10 times to reach 10243. La iteración depende de condiciones complejas:
# Simular un juego simple donde la salud del jugador disminuye
health = 100
turn = 0
while health > 0 and turn < 10:
damage = 15
health -= damage
turn += 1
print(f"Turn {turn}: Health = {health}")
if health <= 0:
print("Game over!")
else:
print("Survived 10 turns!")Output:
Turn 1: Health = 85
Turn 2: Health = 70
Turn 3: Health = 55
Turn 4: Health = 40
Turn 5: Health = 25
Turn 6: Health = 10
Turn 7: Health = -5
Game over!4. Necesitas más control sobre la lógica de iteración:
# Procesar una cadena pero omitir duplicados consecutivos
text = "bookkeeper"
index = 0
while index < len(text):
char = text[index]
print(char, end="")
# Omitir caracteres idénticos consecutivos
while index < len(text) and text[index] == char:
index += 1
print()Output:
bokeperLa característica clave de los bucles while es la iteración indefinida (indefinite iteration): continúas hasta que una condición se vuelve falsa, pero quizá no sabes de antemano cuándo ocurrirá eso.
12.6.3) Convertir entre for y while
Muchos problemas se pueden resolver con cualquiera de los dos tipos de bucle. Aquí está la misma tarea implementada de ambas formas:
# Usar bucle for: sumar números del 1 al 10
total = 0
for number in range(1, 11):
total += number
print(f"Sum (for loop): {total}")
# Usar bucle while: sumar números del 1 al 10
total = 0
number = 1
while number <= 10:
total += number
number += 1
print(f"Sum (while loop): {total}")Output:
Sum (for loop): 55
Sum (while loop): 55Ambos producen el mismo resultado, pero el bucle for es más conciso y menos propenso a errores: no hay riesgo de olvidar incrementar el contador. Cuando puedas usar cualquiera, prefiere el bucle for.
Sin embargo, algunos problemas se expresan de forma más natural con while:
# Encontrar la primera potencia de 2 mayor que 1000
power = 1
exponent = 0
while power <= 1000:
exponent += 1
power = 2 ** exponent
print(f"2^{exponent} = {power} (first power of 2 > 1000)")Output:
2^10 = 1024 (first power of 2 > 1000)Este problema no encaja de forma natural en un bucle for porque no sabemos de antemano cuántas iteraciones necesitamos: estamos buscando un valor que cumpla una condición.
En este capítulo, hemos explorado el bucle for de Python, que proporciona una forma limpia y potente de iterar sobre secuencias. Aprendimos cómo range() genera secuencias numéricas para operaciones de conteo, cómo controlar el flujo del bucle con break y continue, y cómo el patrón for-else maneja elegantemente operaciones de búsqueda. También examinamos cuándo elegir bucles for frente a bucles while según la naturaleza de tu tarea de iteración.
El bucle for es una de las características más utilizadas de Python. A medida que sigas aprendiendo Python, usarás bucles for constantemente—procesando datos de archivos, trabajando con listas y diccionarios, y transformando colecciones de información. En el próximo capítulo, exploraremos la sentencia match de Python, que proporciona otra forma de tomar decisiones basadas en valores, ofreciendo una alternativa más estructurada a largas cadenas if-elif para ciertos tipos de problemas.