Condiciones y bucles en Python

Captura 20150628 - 3El otro día empezaba con Python trabajando sobre una orden directa (print("Hola, mundo") y alguna variante), por lo que, aunque muy poco, ya tienes una noción de cómo se le pide a un ordenador que haga cosas por nosotros. Antes de empezar a contar cosas exhaustivas sobre el lenguaje y su tratamiento de los tipos de datos, y demás, que sería muy árido, prefiero escribir un par de artículos sobre lógica de control.

La lógica de control de un programa es aquello que hace que la ejecución de un programa vaya por un camino o por otro, en función de alguna comprobación. Permite establecer repeticiones y condiciones sobre los datos de entrada para producir algún resultado, y por lo tanto es una pieza fundamental para construir un algoritmo con cualquier lenguaje de programación. Aporta mucho más valor hablar de esto a estas alturas, porque permite empezar a decirle a un programa cómo interpretar datos y tomar decisiones sobre ellos.

Dentro de la lógica de control, en este artículo voy a hablar de bucles y condiciones, así que manos al teclado.

Abre IDLE en la Raspberry con el icono de Python 3, o en Windows o Mac como explicamos en su día.

Expresiones lógicas

Una expresión lógica es algo verdadero o falso. Por ejemplo, sabemos que 3 es mayor que 2, por lo tanto es verdadero. Si pensamos en “2 es mayor que 3”, es falso. Este tipo de expresiones están plenamente soportadas en cualquier lenguaje de programación, y en Python tenemos las de la siguiente tabla:

Expresión Resultado Operador  Ejemplo
Verdadero Verdadero siempre True True
Falso Falso siempre False False
Distinto Verdadero (True) si los dos operandos
son diferentes; falso (False) si no
!= 3 != 2
es True
Igualdad Verdadero (True) si los dos operandos
son iguales; falso (False) si no
== 3 == 3
es True
Mayor que Verdadero (True) si el miembro izquierdo
es mayor; falso (False) si no
> 3 > 3
es False
Mayor o igual que Verdadero (True) si el miembro izquierdo
es mayor o igual; falso (False) si no
>= 3 >= 3
es True
Menor que Verdadero (True) si el miembro izquierdo
es menor; falso (False) si no
< 3 < 3
es False
Menor o igual que Verdadero (True) si el miembro izquierdo
es menor o igual; falso (False) si no
<= 3 <= 3
es True
Negación Verdadero (True) si la expresión a su
derecha es falsa (False); falso (False) si
no
not not 3 < 2
es True
Y lógico Verdadero (True) si la expresión a su
izquierda es verdadera y también la
expresióna su derecha. Falso (False) en
cualquier otro caso
and 3 <= 3 and 3 > 2
es True.
O lógico Verdadero (True) si la expresión a su
izquierda es verdadera o lo es la
expresión a su derecha. Falso (False)
sólo en caso de que las dos sean falsas.
or 4 <= 3 or 3 > 2
es True.

Lógicamente, comparar literales como en la tabla no tiene mucha utilidad. Pero en la entrada anterior de Python hemos aprendido a usar variables, y en ese caso sí tiene sentido.

También podemos combinar condiciones con paréntesis y los operadores de negación, “Y” y “O” que vimos en la tabla superior. Por ejemplo, podemos escribir en Python:

not ( 2 > 3 and 7 > 2 ) or 5 == 6

Es una expresión que evalúa a True y que puedes probar a copiarla del blog y pegarla en IDLE para evaluarla:

Captura de pantalla 2015-06-28 13.37.42

Merece la pena que dediques un tiempo a experimentar con el entorno, escribiendo expresiones para comprobar cómo son evaluadas. Sobre todo, para familiarizarte con la forma de expresarlas y con cosas como, por ejemplo, que puedes combinarlas con aritmética y variables de una forma totalmente intuitiva. Por ejemplo, prueba los ejemplos de la tabla (3 != 2,…) y las siguientes variaciones:

numero = 2
numero >= 2
numero == 3
numero != numero * numero
numero = 1
numero != numero * numero
...

Fíjate también en la diferencia entre el operador de asignación (=) y el comparador de igualdad (==).

Condiciones

Echa un vistazo a la siguiente expresión:

if 2 > 3:
    print("Python no funciona: cree que 2 es mayor que 3.")
elif 2 == 3:
    print("Tampoco: ahora cree que 2 es igual a 3.")
else:
    print("Efectivamente, 2 es menor que 3. Y así debe ser.")

Si sabes inglés y con los conocimientos que ya tienes de Python, habrás reconocido claramente un discurso parecido a este:

Si 2 es mayor que 3, imprime “Python no funciona: cree que 2 es mayor que 3.”. Si, por otro lado, 2 es igual a 3, imprime “Tampoco: ahora cree que 2 es igual a 3.”. En otro caso, imprime “Efectivamente, 2 es menor que 3. Y así debe ser.”

Si no sabes inglés, simplemente te faltaba por saber que if significa “si”, sin tilde, condicional; else significa “en otro caso”, o “si no”; elif es simplemente una contracción de else e if. La parte de elif se podría haber omitido (es opcional) o repetido muchas veces, para evaluar toda una retahíla de condiciones alternativas. El final de la construcción, else, también es opcional pero sólo puede escribirse una vez.

Es obvio que el resultado de la sentencia de ejemplo va a ser la frase “Efectivamente, 2 es menor que 3. Y así debe ser.”. Puedes copiarla entera y pegarla en IDLE, pulsando la tecla intro dos veces para evaluarla:

Captura 20150628

Así, queda clara la estructura de las condiciones en Python: se escriben usando la sentencia compuesta if… elif… else. Nos proporciona una forma de especificar una condición principal que, si se cumple, ejecuta un bloque de código. Para los casos en los que esa condición no se cumpla, podremos opcionalmente especificar una serie arbitrariamente larga de condiciones alternativas que, si se cumpliesen, harían que el intérprete de Python ejecutase otros bloques de código. Por último podremos especificar opcionalmente un último miembro que se ejecutará si todo lo demás es falso.

Las condiciones de esta sentencia compuesta son excluyentes, tal y como marcan las conjunciones inglesas “else”, que podemos entender como “por el contrario”. if… elif… else especifica lo que se conoce como un árbol de reglas: en el momento en el que se cumple una de sus condiciones, el código toma una dirección y el resto del árbol no se evalúa. Es algo que quiero enfatizar de forma muy clara con un ejemplo:

i

if 3 > 2:
    print ("3 es mayor que 2.")
elif 3 < 5:
    print ("3 es menor que 3.")
elif 4 < 9:
    print ("4 es menor que 9.")
else:
    print ("Si lees esto, no sé qué está pasando.")

En el bloque superior, todas las condiciones son ciertas. Sin embargo (puedes comprobarlo) sólo se va a imprimir la primera cadena, “3 es mayor que 2.”. En cuanto Python encuentra una rama del árbol que se cumple, ejecuta su bloque y termina. Ni siquiera se ha molestado en evaluar el resto de las reglas.

Captura 20150628 - 2

Si quisiéramos evaluar estas reglas en cascada en lugar de en forma de árbol, es decir, una detrás de otra, deberíamos haber escrito lo siguiente (si lo intentas copiar todo en un bloque no funcionará, copia de una en una):

if 3 > 2:
    print ("3 es mayor que 2.")
if 3 < 5:
    print ("3 es menor que 5.")
if 4 < 9:
    print ("4 es menor que 9.")
if not (3 > 2 and 3 < 5 and 4 < 9):
    print ("Si lees esto, no sé qué está pasando.")

Si las transcribes todas, por cierto, verás que la última no se ejecuta. Esa condición compuesta es equivalente a un else con respecto a todas las anteriores.

Con esto vamos a dejar aquí el tema de las condiciones, consciente de que ha sido largo. Programar es como hacer deporte: se gana maestría con la práctica. Plantéate pruebas que hacer y, si encuentras alguna duda que no eres capaz de resolver, deja un comentario o escribe a través del formulario de contacto.

Bucles

Un bucle especifica una serie de condiciones que determinarán si se ejecuta un bloque de código una y otra vez. Cada vez que se cumplen las condiciones adecuadas, se ejecuta una pasada por el bucle, o una iteración. El código que se ejecuta dentro del bucle puede ser cualquier cosa: condiciones, otros bucles, o cualquier otro tipo de sentencias.

Vamos a ver los dos bucles de Python while y for, para aclarar esos conceptos.

Bucle while… else

while es una palabra que, en inglés, significa “mientras”. Si, con esto en mente, vemos el siguiente código, entenderemos de forma sencilla lo que hará:

numero = 0
while numero < 3:
    print (numero, "es menor que 3.")
    numero = numero + 1
else:
    print ("numero vale ", numero, ": se sale del bucle.")

Esa construcción significa que, mientras el valor de la variable numero valga menos que 3, el programa imprimirá este hecho e incrementará su valor en una unidad. Por lo tanto, deberíamos ver 3 impresiones por la pantalla: la correspondiente a cuando numero vale 0 (primera iteración), cuando vale 1 (segunda iteración) y cuando vale 2 (tercera iteración).

Cuando numero vale 3 la condición no se cumple, y por lo tanto se abandona el bucle a través de un viejo conocido, else. En los bucles de Python, una palabra else permite especificar qué se ejecuta cuando la condición del bucle deja de cumplirse. Al igual que en las condiciones if… elif… else, la parte else es opcional.

Si vas a copiar y pegar el código de arriba, fallará si lo haces en un sólo intento. Primero copia la sentencia numero = 0 y luego la estructura del bucle while… else. Después del while… else deberás pulsar 2 veces la tecla intro.

El resultado es el siguiente:

Captura 20150628 - 3 + else

Los bucles pueden alojar cualquier tipo de código en su interior, incluyendo, por supuesto, condiciones como las que conocemos. Para explicar esto y además introducir dos palabras especiales de Python relacionadas con el control de los bucles, vamos a ver otro ejemplo. Para ello, antes, voy a introducir el operador aritmético que calcula el resto de una división, que es el “%“. Por ejemplo, “27 % 3” daría 0, puesto que el resto de dividir 27 entre 3 es cero. “28 % 3“, por su parte, tendría como resultado 1. Puedes probarlo en IDLE.

Veamos ya el ejemplo siguiente para entender las palabras break, que significa “romper” y continue, que significa “continuar”:

numero = 0
while numero < 100:
    if numero == 14:
        break
    if numero % 2 == 0:
        print ("El número ", numero, "es par.")
    else:
        print ("El número ", numero, "es impar.")
    numero = numero +1
    continue
    print ("Esto nunca se ejecuta")
else:
    print("Se sale del bucle...")

Si ejecutas ese código en IDLE obtendrás como resultado el siguiente:

Captura 20150628 - 4

Probablemente estéis algo despistados a la primera, pero si reflexionáis las dudas se aclaran por sí solas. Vamos a ver por qué el bucle sólo se ejecuta 13 veces y por qué nunca se escribe la frase “Esto nunca se ejecuta”, ni “Se sale del bucle…”, tratando de leer en voz alta y en español el código de arriba:

Asignamos a la variable numero el valor 0.
Mientras el valor de la variable numero sea menor que 100:

  • Si el valor de numero es 14, romper.
  • Si el resto de dividir el valor de numero entre 2 es cero, imprimir que representa un número par. En otro caso, imprimir que el número que representa es impar.
  • Asignar a numero el resultado de sumarle 1 a su valor actual.
  • Continuar.
  • Imprimir un mensaje que dice que “Esto nunca se ejecuta”.

Cuando el valor de la variable numero sea 100, escribir “Se sale del bucle…”

Si reflexionamos sobre la traducción que acabo de escribir y lo que ha pasado, las conclusiones sólo pueden ser 2:

  • En el contexto de un bucle, break significa romper el bucle, y su efecto es dejar de ejecutarlo, para no ejecutar más iteraciones aunque se cumpla la condición de continuidad. Tampoco se va a ejecutar el bloque else, para mayor confusión.
  • En el contexto de un bucle, continue significa continuar con la siguiente iteración del bucle, y su efecto es dejar de ejecutar el bloque de código de la iteración actual, para pasar a evaluar la condición de continuidad y, si se debe hacer, ejecutar la siguiente iteración.

Mucha gente, entre la que me cuento, está en contra del uso de continue y break, porque en programas grandes hace que el programa sea más difícil de entender, y que cueste más trabajo evolucionarlo o corregir algún error. Representan recursos para un programador vago, que debe modificar el comportamiento de un bucle y decide hacerlo sin mejorar la condición. Metiendo la tijera y cortando por lo sano, dejando código muerto, es decir, sentencias que nunca se ejecutarán, y muchas otras medidas que sólo pueden ser definidas como… baratas.

Sin embargo, eso no quita que son dos conceptos que se deben explicar para que seáis vosotros quienes, desde el conocimiento, decidáis cómo programar y busquéis vuestro estilo. Para los que, como yo, consideramos continue y break algo no demasiado elegante, el bucle debería haber sido escrito de otra forma que, en este ejemplo, está clarísima:

numero = 0
while numero < 14:
    if numero % 2 == 0:
        print ("El número ", numero, "es par.")
    else:
        print ("El número ", numero, "es impar.")
    numero = numero +1
else:
    print ("Se sale del bucle, pues numero = ", numero, ".")

Pruébalo para hacerte una mejor composición de lugar.

Bucle for… else

El bucle for es algo más sofisticado que el while. Mientras que el bucle while está pensado de forma genérica, para aplicarlo a cualquier propósito, el bucle for está pensado para recorrer listas o conjuntos.

Un conjunto en Python es, como en la vida misma, una colección de valores. Se expresa de la siguiente forma: {valor_1, valor_2, valor_3,...}: los valores se separan por comas y el conjunto se delimita mediante llaves.

Por ejemplo, escribe en IDLE lo siguiente, sucesivamente:

{1, 2, 3}
numeros = {1, 2, 3}
numeros

El resultado el que sigue, y como verás, se puede asignar un conjunto a una variable de forma totalmente idéntica a hacer otras asignaciones “individuales”.

Captura 20150628 - 6

Ahora fíjate en el siguiente ejemplo:

colores = {"rojo", "verde", "azul"}
for color in colores:
    print ("El ", color, " es un color.")
else:
    print ("La lista se ha agotado")

Su resultado es el siguiente:

Captura 20150628 - 7 + else

Lo que ha ocurrido ahí es lo siguiente:

  • Hemos definido un conjunto con tres colores
  • Para (todos) los colores en el conjunto, imprimimos un mensaje

Las palabras clave aquí son for e in y en inglés significan “para” y “en”, respectivamente. En Python, for (para) tienen más matices que simplemente los del inglés, corresponde directamente con el texto que arriba dejé marcado en negrita: para todos: el bucle for recorre todos los elementos del conjunto o de la lista si usamos una (son cosas diferentes, como ya veremos), y no permite saltarse ninguno.

Al bucle for aplican exactamente las mismas consideraciones que al bucle while, por lo que ha llegado ya el momento de dejar de teorizar y hacer algún ejercicio.

EJERCICIOS

1) Escribe un bucle que imprima los números pares comprendidos entre el 1 y el 100, pero no aquellos que sean múltiplos de 3 ni múltiplos de 4, y sin usar ni break ni continue. Hazlo dos veces: con while y con for.

Deberás obtener estos resultados:

Captura 20150628 - 5

Pista: para el bucle for puedes generar todos los números del 1 al 100 de la siguiente forma:

del1al100 = range(1, 101)

2) Usando for, haz que Python escriba todas las tablas de multiplicar, del 1 al 10, obteniendo algo como esto:

Captura 20150628 - 8

Algunas notas más

En la documentación oficial de Python (en inglés), todas las sentencias de Python se describen de una forma estandarizada y esquemática que merece la pena examinar ahora con if… elif… else, para cuando queráis consultar alguna sentencia:

"if" expresión ":" suite
( "elif" expresión ":" suite )*
["else" ":" suite]

¿Cómo se interpreta eso?

  • Lo que va entre comillas es literal, es decir, donde pone “if” lo que quiere decir es que hay que escribir eso mismo, “if”. Lo mismo con los dos puntos, el “elif” y el “else”.
  • Lo que no va entre comillas quiere decir que ahí va código en Python.
    • En el caso de la expresión, se trata de una expresión del lenguaje que vale verdadero o falso, como veíamos antes
    • En el caso de suite, lo que quiere decir es que ahí va un bloque de sentencias en Python: instrucciones que hacen cosas al respecto si la expresión vale verdadero. Esto incluye cualquier cosa, incluyendo bucles y otras sentencias if… elif… else, caso en el que tendríamos condiciones anidadas.
  • Lo que va entre paréntesis y con un asterisco (*) al cierre puede repetirse ninguna o muchas veces (arbitrariamente). En el caso de `( “elif” expresión “:” suite)*`, tenemos lo siguiente:
    • El paréntesis simplemente agrupa.
    • El asterisco (*) significa “0 ó varias veces”.
    • Si fuese un signo más (+), significaría “1 ó varias veces”.
  • Lo que va entre corchetes ([, ]) es un grupo que puede aparecer ninguna o una vez, es decir, un “opcional de toda la vida”: `[“else” “:” suite]` podría usarse, o no.

4 comentarios en “Condiciones y bucles en Python

  1. En este ejercicio:
    numero = 0
    while numero < 100:
    if numero == 14:
    break
    if numero % 2 == 0:
    print ("El número ", numero, "es par.")
    else:
    print ("El número ", numero, "es impar.")
    numero = numero +1
    continue
    print ("Esto nunca se ejecuta")
    else:
    print("Se sale del bucle…")

    Me da error y lo he modificado,
    numero = 0
    while numero < 100:
    if numero == 14:
    break
    if numero % 2 == 0:
    print ("El número ", numero, "es par.")
    numero = numero +1
    else:
    print ("El número ", numero, "es impar.")
    numero = numero +1
    continue
    print ("Esto nunca se ejecuta")
    Le he añadido bajo el condicional del numero par "numero = numero +1"
    Y le he tenido que quitar el último else: para que funcione.
    ¿Esto es así?

    1. Lo acabo de comprobar y he visto que hay un error de tabulaciones en el formateado del código. La línea del incremento “numero = numero+1” y el último “else” tienen un tabulador de más, por eso no funciona.

      Ahora mismo lo corrijo en el artículo. ¡Muchas gracias!

      1. Muchas gracias Gabriel, me he llevado mucho tiempo buscando la solución y la verdad es que lo de las tabulaciones no lo tenía nada claro, ya no creo que se me olvide.

        Saludos y agradecerte tu labor, y lo ágil de la corrección,
        ÁNGELA

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *