Apéndice H — Control de flujo.

Objetivo. Revisar las declaraciones para control de flujo de un código y mostrar ejemplos de su uso.

H.1 Declaraciones de control de flujo.

En Python existen declaraciones que permiten controlar el flujo de un programa para realizar acciones complejas. Entre estas declaraciones tenemos las siguientes:

  • while
  • for
  • if
  • match

Junto con estas declaraciones generalmente se utilizan las siguientes operaciones lógicas cuyo resultado puede ser True o False:

Python Significado
a == b ¿son iguales a y b?
a != b ¿son diferentes a y b?
a < b ¿a es menor que b?:
a <= b ¿a es menor o igual que b?
a > b ¿a es mayor que b?
a >= b ¿a es mayor o igual que b?
not A El inverso de la expresión A
A and B ¿La expresión A y la expresión B son verdaderas?
A or B ¿La expresión A o la expresión B es verdadera?:

H.2 while

Se utiliza para repetir un conjunto de instrucciones mientras una expresión sea verdadera:

while expresión:
    código ...
Ejemplo H.1: Repetir hasta cumplir una condición 1.

Imprimir el valor de una variable a que inicia en 0 y que se va incrementando en 1 hasta que se cumple que a < 5.

# Inicializamos a en 0
a = 0 

# Imprimimos las condiciones antes del ciclo while
print("Antes del while: a = {}, ¿a < 5? = {}".format(a, a < 5)) 

while a < 5: # Mientras 'a' sea menor que 5 realiza lo siguiente:
    a += 1   # Incrementamos el valor de 'a' en 1
    print("a = {}, ¿a < 5? = {}".format(a, a < 5)) # Revisamos las condiciones
    
print('Finaliza while')  # Instrucción fuera del bloque while
Antes del while: a = 0, ¿a < 5? = True
a = 1, ¿a < 5? = True
a = 2, ¿a < 5? = True
a = 3, ¿a < 5? = True
a = 4, ¿a < 5? = True
a = 5, ¿a < 5? = False
Finaliza while

Observaciones.

  • En el código anterior, las dos líneas de código que están abajo del while se repiten 5 veces.
  • Esta repetición se termina cuando la expresión a < 5 ya no es verdadera.
  • Observa que dentro del ciclo se encuentra la instrucción a += 1 que va incrementando el valor de a en cada iteración.
  • También hay una instrucción para imprimir el resultado de cada iteración.

H.2.1 Reglas de la sangría

  • Como puedes observar en el Ejemplo H.1, el código debajo de la instrucción while tiene una sangría (indentation): las líneas de código están recorridas hacia la derecha. Este espacio en blanco debe ser al menos de uno, pero pueden ser más.
  • Por omisión, en JupyterLab (y algunos otros editores), se usan 4 espacios en blanco para cada línea de código dentro del bloque.
  • El número de espacios en blanco se debe mantener durante todo el bloque de código.
  • Cuando termina la sangría, es decir cuando las líneas de código ya no tienen ningún espacio en blanco al inicio, se cierra el bloque de código, en este caso el while.
  • Las reglas de la sangría son iguales en otras declaraciones como for, if ... elif ... else, match, entre otras.
  • El uso de una sangría para organizar los bloques de código hace que los programas en Python sean más claros.
Ejemplo H.2: Repetir hasta cumplir una condición 2.

En los siguientes ejemplos de while el código dentro del bloque está alineado correctamente.

a = 0
while a < 5: 
 print("a =",a)
 a += 1
a = 0
a = 1
a = 2
a = 3
a = 4
a = 0
while a < 5: 
        print("a =",a)
        a += 1
a = 0
a = 1
a = 2
a = 3
a = 4

.

Ejemplo H.3: Sangría errónea.

En los siguientes ejemplos de while la líneas de código del bloque están incorrectamente alineadas, de tal manera que al ejecutarlos obtendrás un error como el siguiente:

IndentationError: unexpected indent

y te indicará el lugar donde la alineación no es correcta.

a = 0
while a < 5: 
 print("a =",a)
   a += 1
  Cell In[4], line 4
    a += 1
    ^
IndentationError: unexpected indent
a = 0
while a < 5: 
print(a)
a += 1
  Cell In[5], line 3
    print(a)
    ^
IndentationError: expected an indented block after 'while' statement on line 2

H.3 for

  • Esta declaración permite iterar sobre el contenido de cualquier secuencia.
  • Las secuencias son objetos que contienen varios elementos, un ejemplo es una cadena que contiene caracteres.
  • En Python se tienen varios tipos de secuencias como listas, tuplas, conjuntos, diccionarios, archivos, entre otros. Más adelante describiremos estas secuencias.

El for se declara como sigue:

for i in secuencia:
    codigo ...

Las reglas de la sangría que se deben seguir son las mismas que las descrita para la instrucción while.

Veamos un ejemplo simple:

# Definimos una cadena
cadena = "El objetivo de un viaje es sólo el inicio de otro viaje"

# Recorremos cada elemento de la 'cadena' y los imprimimos separados 
# por un guion usando un ciclo 'for':
for c in cadena:
    print(c, end="-")
E-l- -o-b-j-e-t-i-v-o- -d-e- -u-n- -v-i-a-j-e- -e-s- -s-ó-l-o- -e-l- -i-n-i-c-i-o- -d-e- -o-t-r-o- -v-i-a-j-e-
  • El ciclo for recorre la secuencia, que en este caso es un str almacenado en la variable cadena;
  • La variable c, dentro de la declaración for, va tomando cada elemento de cadena (en este caso, cada caracter).
  • La única instrucción que se tiene en el bloque de código es imprimir cada caracter; se usa la opción end="-" para separar cada caracter con un guion.
  • Observa que los espacios se consideran también elementos de la cadena.

H.3.1 Función range

Una secuencia que es muy usada en conjunto con el ciclo for es la que se genera con la función range(). Esta función genera una secuencia iterable con un inicio, un final y un salto, su forma es la siguiente:

range(start, stop, step)

La secuencia iniciará en start y terminará en stop-1 en pasos de tamaño step.

Ejemplo H.4: Repetir un número de veces.

Usando un ciclo for y secuencias range() realiza lo siguiente:

  1. Imprime los números del 1 al 20 .
  2. Imprime los número impares del 1 al 19.
  3. Imprime la secuencia de números: 20, 19, ..., 1.
  4. Imprime la secuencia de números: -5, -3, -1, 1, 3,
# 1.
for i in range(1, 21): # Por omisión step = 1
    print(i, end= ', ')
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 

Observa que en el ejemplo anterior no se imprime el 21.

# 2.
for i in range(1, 21, 2): # saltos de dos en dos
    print(i, end= ', ')
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 
# 3.
for i in range(20, 0, -1): # El paso puede ser negativo
    print(i, end= ', ')
20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 

Observa que en el ejemplo anterior no se imprime el 0.

# 4.
for i in range(-5,5,2):  # El rango puede comenzar en valores negativos 
    print(i, end= ', ')
-5, -3, -1, 1, 3, 

Observa que en el ejemplo anterior no se imprime el 5.

H.4 if, elif, else

Esta declaración permite ejecutar bloques de código dependiendo del resultado de una o varias expresiones lógicas. La estructura es como sigue:

if expresion1:
    codigo1 
    ...
elif expresion2:
    codigo2 
    ...
elif expresion3:
    codigo3 
    ...
else:
    codigo4
    ...
  • Si la expresion1 es verdadera, entonces se ejecuta el codigo1.
  • En otro caso se evalúan las siguientes expresiones y dependiendo de cuál es verdadera se ejecuta el código correspondiente.
  • Cuando ninguna de las expresiones es verdadera, entonces se ejecuta el código de la sección else, es decir el codigo4.

Observa que se siguen las mismas reglas de sangría que en el while.

Veamos un ejemplo:

a = 30
b = 10
if a < b:
    print('a es menor que b')
elif a > b:
    print('a es mayor que b')
else:
    print('a es igual a b')
a es mayor que b
  • Usando los valores originales a = 30 y b = 10 obtenemos el resultado a es mayor que b.
  • Ahora modifica los valores a los siguientes a = 10 y b = 30 y verifica que el resultado es a es menor que b.
  • Finalmente usa los valores a = 10 y b = 10 y verifica que el resultado sea correcto.

Las expresiones pueden ser más elaboradas:

a = 30
b = 10
print(f'a = {a}, b = {b}')

if (a < b) or (a > b):
    print(f'¿a < b? = {a < b}, ¿a > b? = {a > b}')
else:
    print("a y b son iguales")
a = 30, b = 10
¿a < b? = False, ¿a > b? = True

Cambia los valores de a y b de manera similar que en el ejemplo anterior y observa el resultado.

Ejemplo H.5: Impares.

Implementa un código que imprima los número impares en el rango (-N, N), donde N es un valor entero positivo que es ingresado por el usuario.

# Se obtiene el valor de N
N = int(input("N ="))

# Se recorre el rango de números
for n in range(-N, N+1, 1):
    if n % 2: # Se cumple cuando la operación módulo genera un residuo diferente de cero (n = impar)
        print(n, end = ", ")
N = 5
-5, -3, -1, 1, 3, 5, 

H.5 Sangría en varios bloques de código

En el ejemplo anterior, observa que se están anidando dos bloques de código:

  • El ciclo for n in range(-N, N+1, 1): contiene la instrucción if n % 2: dentro de su bloque de código y tiene 4 espacios a la izquierda para indicar que es parte del ciclo for.
  • El condicional if n % 2: contiene una llamada a la función print() dentro de su bloque de código que tiene 8 espacios a la izquierda para indicar que es parte del if.
  • Es necesario mantener alineadas las instrucciones que pertenecen a cada bloque de código, de otra manera obtendrás resultados inesperados o incluso errores.
  • Se pueden anidar tantos bloques de código como se requieran, solo se debe de ser muy consistente para definir la terminación de cada bloque de código. Veamos el siguiente ejemplo:
Ejemplo H.6: Sangrías anidadas.

Considera el siguiente código:

N = 5
for n in range(-N, N+1, 1):
    print(f"\nChecando el número {n} ...")
    np = abs(n)
    if n % 2:
        print(f"{n} es impar")
        for i in range(-np, np+1):
            print(f"{i}", end=",")
    else:
        print(f"{n} es par")
        for i in range(-np, np+1):
            print(f"{i}", end=",")
    print("\nTerminando el chequeo")

En el código anterior se tienen los siguientes bloques de código:

  1. Nivel cero sangría:
N = 5
for n in range(-N, N+1, 1): 
  1. Nivel uno: 4 espacios, bloque del ciclo for
    print(f"\nChecando el número {n} ...")
    np = abs(n)
    if n % 2:
        ...
    else:
        ...
    print("\nTerminando el chequeo")
  1. Nivel dos: 8 espacios, bloque del condicional if ... else ...
        print(f"{n} es impar")
        for i in range(-np, np+1):
        ...
        print(f"{n} es par")
        for i in range(-np, np+1):
        ...
  1. Nivel tres: 12 espacios, bloques de dos ciclos for
            print(f"{i}", end=",")
            ...
            print(f"{i}", end=",")


En la siguiente celda escribimos el código anterior respetando todos los espacios y sangrías. Observa el resultado y trata de explicar lo que hace.

N = 5
for n in range(-N, N+1, 1):
    print(f"\nChecando el número {n} ...")
    np = abs(n)
    if n % 2:
        print(f"{n} es impar. En el rango ({-np},{np}) tenemos:")
        for i in range(-np, np+1, 2):
            print(f"{i}", end=",")
    else:
        print(f"{n} es par. En el rango ({-np},{np}) tenemos:")
        for i in range(-np, np+1, 2):
            print(f"{i}", end=",")
    print("\nTerminando el chequeo")

Checando el número -5 ...
-5 es impar. En el rango (-5,5) tenemos:
-5,-3,-1,1,3,5,
Terminando el chequeo

Checando el número -4 ...
-4 es par. En el rango (-4,4) tenemos:
-4,-2,0,2,4,
Terminando el chequeo

Checando el número -3 ...
-3 es impar. En el rango (-3,3) tenemos:
-3,-1,1,3,
Terminando el chequeo

Checando el número -2 ...
-2 es par. En el rango (-2,2) tenemos:
-2,0,2,
Terminando el chequeo

Checando el número -1 ...
-1 es impar. En el rango (-1,1) tenemos:
-1,1,
Terminando el chequeo

Checando el número 0 ...
0 es par. En el rango (0,0) tenemos:
0,
Terminando el chequeo

Checando el número 1 ...
1 es impar. En el rango (-1,1) tenemos:
-1,1,
Terminando el chequeo

Checando el número 2 ...
2 es par. En el rango (-2,2) tenemos:
-2,0,2,
Terminando el chequeo

Checando el número 3 ...
3 es impar. En el rango (-3,3) tenemos:
-3,-1,1,3,
Terminando el chequeo

Checando el número 4 ...
4 es par. En el rango (-4,4) tenemos:
-4,-2,0,2,4,
Terminando el chequeo

Checando el número 5 ...
5 es impar. En el rango (-5,5) tenemos:
-5,-3,-1,1,3,5,
Terminando el chequeo

H.6 Operador ternario

Este operador permite evaluar una expresión lógica y generar un valor para un resultado True y otro diferente para un resultado False; todo esto se logra en una sola línea de código como sigue:

resultado = valor1 if expresion else valor2

En este código la variable resultado tendrá el valor valor1 si la expresion es verdadera o el valor2 si la expresión es falsa.

Ejemplo H.7: Operador ternario.

Verificar si el valor de la variable c es mayor que 5.

# Inicializamos c
c = 1

# Evaluamos ¿c > 5? y determinamos el valor de r
r = c if c > 5 else 0

# Se imprime el valor de c
print(f"c = {c}") 

# Se imprime el resultado de la prueba: c > 5 (puede ser False o True)
print(f"¿c > 5? {c > 5}")  

# Se imprime el valor r (que depende del resultado de: c < 5)
print(f"r = {r}") 
c = 1
¿c > 5? False
r = 0

En la celda anterior modifica el valor de c a 6 y ve lo que sucede.

Podemos probar para varios valores de c usando un ciclo for como se muestra a continuación:

for c in range(1,10):
    r = c if c > 5 else 0
    print(f"c = {c},", f"¿c > 5? = {c > 5},", f"r = {r}")
c = 1, ¿c > 5? = False, r = 0
c = 2, ¿c > 5? = False, r = 0
c = 3, ¿c > 5? = False, r = 0
c = 4, ¿c > 5? = False, r = 0
c = 5, ¿c > 5? = False, r = 0
c = 6, ¿c > 5? = True, r = 6
c = 7, ¿c > 5? = True, r = 7
c = 8, ¿c > 5? = True, r = 8
c = 9, ¿c > 5? = True, r = 9

H.7 break, continue, else, pass

Estas son palabras clave que se pueden usar en ciclos while o for:

  • break: terminar el ciclo más interno.
  • continue: saltarse a la siguiente iteración sin terminar de ejecutar el código que sigue.
  • else: NO se ejecuta el código de esta cláusula si el ciclo es finalizado por el break. Si el ciclo no llega a la instrucción break entonces se ejecuta el código implementado dentro del else.
  • pass: no hacer nada y continuar.

Veamos algunos ejemplos.

Ejemplo H.8: break.

Recorrer una cadena para encontrar una letra; una vez encontrada terminar el proceso.

# Recorremos una cadena
for letra in "Hola mundo Pythonico":
    print(f"letra: {letra}")
    if letra == "u":   # Si la letra es la 'u'
        break          # entonces se termina el ciclo
letra: H
letra: o
letra: l
letra: a
letra:  
letra: m
letra: u

Se puede agregar un else alineado con el for. El código dentro del else será ejecutado cuando no se alcanzó a ejecutar la condición break.

En el ejemplo que sigue, prueba primero con la letra u y luego con r.

c = input("Caracter a buscar: ")

for letra in "Hola mundo Pythonico":
    print(f"letra: {letra}")
    if letra == c:
        print(f"Letra '{c}' encontrada")
        break
else: # Se ejecuta cuando el ciclo termina sin llegar al break
    print(f"No encontré la letra: '{c}'")
Caracter a buscar:  u
letra: H
letra: o
letra: l
letra: a
letra:  
letra: m
letra: u
Letra 'u' encontrada

.

Ejemplo H.9: continue.

Imprimir cuándo un número es par entre los números 0 a 11.

for n in range(0, 11):
    if n % 2:  # Cuando n % 2 es diferente de cero, el número es impar
        continue # no se hace nada, termina esta iteración y se pasa al siguiente número
    print(f"Número par {n}") # Se ejecuta solo cuando el número es par
Número par 0
Número par 2
Número par 4
Número par 6
Número par 8
Número par 10

.

Ejemplo H.10: pass.

Esta declaración no hace nada y generalmente se usa principalmente para cuestiones de desarrollo de código a un nivel abstracto. Por ejemplo si aún no tenemos claro que se va a realizar dentro de un ciclo o de una función, podemos simplemente poner esta declaración y dejar la implemetación para más adelante.

i = 0

# Aún no sabemos el código que debemos implementar
while i < 10:
    print("Aquí va el código del while")
    i = 11 # Para que solo se haga una vez el ciclo
    pass
Aquí va el código del while
# La siguiente función debe calcular la secuencia de Fibonacci
def fib(n):
    print("Aquí va el código de la función: n = {}".format(n))
    pass

# En este punto del programa requiero el uso de la función fib(n):
fib(100000) # 
Aquí va el código de la función: n = 100000
NotaNota.

Observa que en el último ejemplo estamos usando la declaración de una función usando def; más ejemplos sobre funciones los puedes encontrar en el Apéndice O.

H.8 match (desde la versión 3.10)

Esta declaración es parte de Python a partir de la versión 3.10. Permite buscar coincidencias de patrones de una manera similar a la instrucción switch-case de otros lenguajes de programación (C/C++, Java).

Veamos algunos ejemplos:

x = int(input("Teclea 1 o 0 por favor"))

match x:
    case 0:
        print("Tecleaste el número entero cero")
    case 1:
        print("Tecleaste el número entero uno")
    case _:
        print("Tecleaste algo diferente")
        
Teclea 1 o 0 por favor 5
Tecleaste algo diferente
# Modifica los valores de la siguiente tupla y observa el resultado
point = (0, 0)

match point:
    case (0, 0): # Cuando ambas coordenadas son 0
        print("Origen {}".format(point))
    case (0, y): # Cuando x = 0
        print(f"Y={y}")
    case (x, 0): # Cuando y = 0
        print(f"X={x}")
    case (x, y): # Cuando ambas son distintas de cero
        print(f"X={x}, Y={y}")
    case _: # Cuando no es una tupla con dos elementos
        raise ValueError("No es un punto en el plano XY")
Origen (0, 0)
x = -1
match x:
    case x if x < 0:
        print("Número negativo")
    case x if x == 0:
        print("Cero")
    case x if x > 0:
        print("Número positivo")
    case _:
        print("Cero")
Número negativo
status = 400
match status:
    case 400:
        print(f"{status} Bad request")
    case 404:
        print(f"{status} Not found")
    case 418:
        print(f"{status} Soy una tetera")
    case _:
        print(f"{status} Algo anda mal con el internet")
400 Bad request

Para más detalles véase match Statements