Control del flujo del programa

Normalmente, un programa consta de más de una instrucción, los programas algo complejos necesitan ejecutar una serie de sentencias de forma repetida o elegir entre caminos alternativos según el valor que tiene una variable en el momento de su ejecución.

Para poder realizar las ideas antes descritas necesitamos conocer las diferentes estructuras de control que los lenguajes de programación nos proveen. Una estructura de control dirige el orden de ejecución de las instrucciones de un programa. Todas las estructuras de control tienen un único punto de entrada y un punto de salida. Esto es una de las cosas que permite que la programación se rija por los principios de la programación estructurada. Los programas estructurados están formados por estructuras simples organizadas de forma jerárquica que controlan el flujo de ejecución del programa.

Condicional

En el mundo real, existen muchas situaciones en los que se debe evaluar la información disponible y a continuación elegir entre varias opciones basándonos en lo que hemos observado. Este tipo de patrones no son reproducibles con el esquema de composición secuencial y, por tanto, introduciremos el esquema de composición condicional.

Este esquema responde a estructuras del siguiente tipo:

si llueve
   entonces añado el paraguas
sino
   entonces cojo el gorro

En un programa de Python, la instrucción if sirve para tomar este tipo de decisiones. Permite la ejecución condicional de una declaración o grupo de afirmaciones basada en el valor de una expresión. Su estructura es la siguiente:

if <expr>:
    <cuerpo>

En el código que se muestra arriba <expr> es una expresión evaluada en un contexto booleano y <cuerpo> es una o un conjunto de expresiones de Python válida:nbsphinx-math:es, además fíjate que debe estar tabulada.

En el siguiente ejemplo utilizamos la composición condicional para obtener el valor absoluto de un número:

[3]:
# Programa que calcula el valor absoluto de un numero
x = 12

#Bloque condicional
if x < 0:
    print("Entramos en el bloque condicional")
    x = x * -1  # x*= -1 o també x = -x

print("Estamos fuera del bloque condicional")
# Resultados
print(f'El valor absoluto es: {x}')
Estamos fuera del bloque condicional
El valor absoluto es: 12

Las cláusulas else y elif

Ahora que sabemos cómo utilizar una instrucción if para ejecutar condicionalmente una sola instrucción o un bloque de varias expresiones es hora de averiguar qué más podemos hacer.

Hay problemas en los que queremos evaluar una condición y tomar una ruta si es cierta, pero también poder seguir una ruta alternativa si esta no lo es. Esto se logra con una cláusula les. Por ejemplo si queremos hacer un programa que nos diga si un número es positivo o negativo podemos hacerlo de la siguiente manera:

[ ]:
x = -1

if x > 0:
    print("Evaluamos el número")  # Un bloque con dos sentencias de código
    print("El número es positivo")
else:
    print("El número es negativo")

Realmente el código de sobre no hace del todo bien su trabajo, ya que cuando x toma el valor 0, el programa no contempla ningún caso. Para poder completar y corregir nuestro programa necesitamos evaluar una condición más, lo podemos hacer con la palabra reservada elif.

[2]:
x = 0

if x > 0:
     print("Evaluamos el número") # Un blog con dos sentencias de código.
     print("El número es positivo")

elif x == 0: # Aquí contemplamos que el número pueda ser 0

     print("El número es cero")

else:
# Aquí no necesitamos una nueva condición, si el número no es positivo
# ni cero, seguro que es negativo

     print("El número es negativo")

print("Hasta la próxima vez")
El número es cero
Hasta la próxima vez

Por lo general podemos hacer tantas condiciones como queramos o necesitamos:

if <expr>:
    <cos(+)>
elif <expr>:
    <cos(+)>
elif <expr>:
    <cos(+)>
    ...
else:
    <cos(+)>

Bucles

Otros problemas demandan la repetición del mismo bloque de código más de una vez. Pensemos por ejemplo en el código necesario para calcular una tabla de multiplicar, básicamente consiste en repetir la misma expresión cambiando un de los operandos en cada iteración. La estructura de control que implementa la composición iterativa se llama bucle.

En la programación, existen dos tipos de iteraciones, indefinidas y definidas:

  • Iteración indefinida, la cantidad de veces que se ejecuta el bucle no se explícita. Por el contrario, el bloque designado se ejecuta repetidamente siempre que se cumpla alguna condición lógica, es decir booleana.

  • Iteración definida, se explícita el número de veces que se ejecutará el bloque designado en el momento en que se inicia el bucle, puede realizarse tanto con una variable entera como con un literal.

El bucle indefinido

Para crear iteraciones con un número inicialmente indefinido de repeticiones utilizaremos la instrucción while. En esta sección veremos cómo se emplea esta instrucción para construir programas que contengan bucles.

El formato de un while se muestra a continuación:

while <expr>:
    <cuerpo(+)>

Cuando se encuentra un bucle, la expresión <expr> se valora por primera vez en un contexto booleano. Si el resultado es cierto, entonces se ejecuta el cuerpo del bucle. A continuación, <expr> se valora de nuevo, y si todavía es evaluada como cierta, el cuerpo se ejecuta de nuevo. Este proceso continúa hasta que <expr> es evaluada como False, entonces la ejecución del programa sigue con la primera sentencia más allá del cuerpo del bucle. Fijaos que el cuerpo del bucle va identificado en la expresión while.

Un ejemplo de programa que utiliza un bucle indefinido sería el siguiente. Este programa nos permite hacer una cuenta atrás partiendo del valor de la variable n hasta llegar a 1:

[1]:
n = 5
print("El valor inicial de la variable 'n' es: " + str(5))
while n > 0: # Que pasa cuando n = 0 ?

    print(n)
    n = n - 1

print(f'Valor de n = {n}')
print("Out!")
El valor inicial de la variable 'n' es: 5
5
4
3
2
1
Valor de n = 0
Out!

El bucle definido

Este otro tipo de bucle es más controlado que el anterior, puesto que no finaliza cuando una condición se deja de cumplir, sino que cuando lo definimos también sabemos cuántas iteraciones va a realizar. La instrucción usada en este caso se conoce con el nombre de for y lo explicaremos a continuación.

for <var> in <iterable>:
     <statement(s)>

var es la variable que usaremos en el cuerpo del bucle, no debe definirse con anterioridad. <iterable> es una colección de objetos sobre la que iteraremos, por ejemplo, una lista o una tupla. <statement(s)> en el cuerpo del bucle se denota con indentación tal y como hemos explicado en los condicionales y en los bucles indefinidos, todas las expresiones que forman el <statement(s)> se ejecuta(n) una vez por cada elemento del <iterable>. La variable de bucle <var> asume el valor de cada elemento del <iterable>. Este tipo de bucles se utilizan en conjunto con estructuras de datos como las listas o las tuplas que veremos en la siguiente sección.

A continuación dejamos dos ejemplos a modo ilustrativo:

[2]:
for i in (0,1,2,3,4,5):
    s = i + 3
    print(s)
3
4
5
6
7
8
[ ]:
for i in range(10):
    print(i)

La función range(<inicio>, <final>, <salto>) devuelve un iterable que produce enteros comenzando con <begin>, hasta <end>-1. Si se especifica, <salto> indica el salto entre dos valores consecutivos de la secuencia.

Ejercicios

  1. Realizar un programa que imprima todos los números del 0 al 6 excepto el 3 y el 6.

  2. Escribir un programa que dado un número, \(n\), imprima todos los divisores de ese número.

  3. Escribe una función que recibe tres valores de entrada que corresponden a horas, minutos y segundos. El programa debe indicar si se trata de un reloj con una hora válida.

Si recibimos los números 9, 56, 33 es correcto.
Si recibimos los números 9, 64, 22 no es correcto, ya que no existen los 64 minutos.
Si recibimos los números 25, 44, 22 no es correcto puesto que no existe la hora 25.
  1. Dado un número entero \(n\). Si la suma de sus divisores (sin contar el mismo número) es igual a \(n\), se dice que ese número es perfecto. Si esa suma es inferior, se dice que es deficiente. Si es superior se dice que es abundante. Realiza un programa que dado un número entero nos diga si es perfecto, deficiente o abundante.

  2. Escriba un programa para construir el siguiente patrón:

1
1 1
1 1 1
1 1 1 1
1 1 1 1 1
1 1 1 1
1 1 1
1 1
1
  1. Escribe una función que recibe un número y devuelve True si este es primo y Falseen caso contrario.