2.12. Bucles

Un bucle ejecuta el mismo bloque de código repetidamente. Python tiene dos formas: while, que sigue ejecutándose mientras una condición se mantenga verdadera, y for, que recorre los elementos de una secuencia.

Diagramas de flujo en paralelo. while: comprueba la condición, ejecuta el cuerpo si es verdadera, repite. for: toma el siguiente elemento del iterable, ejecuta el cuerpo, repite hasta agotarlo.

while sigue comprobando una condición; for recorre una secuencia hasta agotarla.

2.12.1. Bucles while

Un bucle while comprueba su condición antes de cada iteración y ejecuta el cuerpo hasta que la prueba se vuelve falsa:

count = 0
while count < 5:
    print(count)
    count += 1

Salida:

0
1
2
3
4

Si la condición es verdadera al inicio y nunca se vuelve falsa, el bucle se ejecuta para siempre. while True: es el modismo estándar para un bucle principal, que se sale explícitamente con break:

while True:
    step()
    if done():
        break

2.12.2. Bucles for

Un bucle for recorre los elementos de un iterable – una lista, tupla, cadena, bytes, diccionario o cualquier otra cosa que admita iteración:

for fruit in ["apple", "banana", "cherry"]:
    print(fruit)

Salida:

apple
banana
cherry

La misma forma funciona sobre una cadena, donde cada elemento es una cadena de un solo carácter:

for letter in "OpenMV":
    print(letter)

Salida:

O
p
e
n
M
V

Iterar un diccionario directamente produce sus claves, en orden de inserción:

for key in {"a": 1, "b": 2}:
    print(key)

Salida:

a
b

Cada pasada vincula la variable del bucle (fruit, letter, key) al siguiente elemento. Después de que el bucle termina, la variable conserva el valor de la última iteración.

2.12.3. range

Para bucles sobre un rango numérico, usa range():

  • range(stop) – 0, 1, …, stop - 1.

  • range(start, stop) – start, start + 1, …, stop - 1.

  • range(start, stop, step) – con un paso personalizado (los valores negativos cuentan hacia atrás).

for i in range(5):           # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 8, 2):     # 2, 4, 6
    print(i)

for i in range(10, 0, -1):   # 10, 9, ..., 1
    print(i)

range() produce valores de forma perezosa – no construye una lista en memoria. Para obtener una list real, envuélvelo: list(range(10)).

2.12.4. enumerate

Cuando el bucle necesita tanto el índice como el elemento, enumerate() produce pares (index, item):

for i, name in enumerate(["a", "b", "c"]):
    print(i, name)
# 0 a
# 1 b
# 2 c

Comienza el índice en algo distinto de cero pasando un segundo argumento: enumerate(items, start=1).

2.12.5. zip

Para recorrer dos (o más) iterables al unísono, usa zip(). Produce una tupla por posición y se detiene en la entrada más corta:

names  = ["alice", "bob", "carol"]
scores = [88, 92, 70]

for name, score in zip(names, scores):
    print(name, score)

Salida:

alice 88
bob 92
carol 70

2.12.6. Asignación en línea con :=

El operador morsa := es una asignación que además es una expresión. Vincula un nombre y se evalúa al mismo valor al mismo tiempo. En un bucle while, esto reduce el patrón habitual de «leer, comprobar, cuerpo» a una sola línea:

# without walrus
value = next_value()
while value is not None:
    process(value)
    value = next_value()

# with walrus
while (value := next_value()) is not None:
    process(value)

Las dos formas hacen lo mismo. Recurre a := cuando la duplicación de la asignación realmente perjudique la legibilidad; no recurras a él solo por presumir. Los paréntesis son obligatorios en la mayoría de las posiciones para mantener la expresión sin ambigüedades.