BUCLE WHILE

 CALLEJÓN ADOQUINADO ENTRE CASAS SEÑERAS EN LA LOCALIDAD DE TAGANANA, NORTE DE ANAGA, NORESTE DE TENERIFE.
      Dentro de la herramientas de control de flujo toca ahora echarle un vistazo al bucle o loop, como prefiramos llamarlo, while. Del mismo modo que sucede con el bucle for/in que ya hemos visto en alguna ocasión y que estudiaremos en el apartado siguiente, se trata de un ITERADOR, esto es, tengámoslo en cuenta, que la condición es aplicada sobre cada elemento de una colección de datos, de uno en uno y por orden, evaluando la condición en cada caso sobre el primer dato que obtiene, luego sobre el segundo, a continuación el tercero y así sucesivamente n número de veces hasta que la condición se cumpla, deteniéndose el bucle, aplicándose en ese momento el bloque de código correspondiente al mismo y haciéndose efectiva la bifurcación.
Esta capacidad intrínseca para iterar que adorna a nuestro bucle while le permite ejecutar una serie de sentencias, agrupadas en su bloque de código, siempre y cuando se cumpla una determinada condición o condiciones, esto es, siempre que el resultado de la evaluación sea True.
Aquí mostramos un pequeño esquema:



Veamos a continuación su sintaxis.
 
                                                                                    WHILE (CONDICIÓN BOOLEANA):
                                                                                               BLOQUE_DE_CÓDIGO


En tanto  que la veracidad de la condición se dilucida con un True o False, la condición debe ser de índole booleana. Ahora veremos un ejemplo práctico sencillo:


En este ejemplo constatamos lo siguiente:
En 1. creamos una variable con el nombre de identificador del espacio de memoria 'num' a la que asignamos el valor inicial 0 mediante el operador = de asignación.
En 2. establecemos un bucle while con la siguiente expresión: num < 10, que es la condición que establecemos. A continuación, recordemos que los bloques de código de las herramientas de control de flujo debe ir sangradas o indentadas, cerramos con dos puntos.
En 3., finalmente, colocamos las declaraciones que, en nuestro ejemplo, van a ser dos instrucciones: primero codificamos una función print() con una string como parámetro para poder mostrar el resultado en pantalla; y a continuación generamos un contador simple. Recurrimos a nuestra variable 'num' que, como sabemos, tiene asignado el valor (en los contadores es preceptivo inicializar la variable con un valor numérico) al que sumamos, +. 1. De esta forma, cuando el bucle while itere por primera vez, devolverá el valor 0, que es el primer valor de 'num'. Como la condición se cumple que da gusto (el valor booleano es True), prosigue con la iteración tras aplicar la declaración 0 + 1, de tal modo, que ahora 'num' vale 1. El bucle while vuelve a iterar tras ejecutarse la operación, y como la condición sigue cumpliéndose (1 es menor que 10), y vuelta a ejecutarse la declaración: ahora 'num' vale 1 y se le suma 1, es decir, 1 + 1 = 2. Como la condición continúa cumpliéndose dado que 2 es menor que 10, aplica la declaración nuevamente, 2 + 1,, es decir, 3, y vuelta a iterar. Todo continúa igual hasta llegar a 9 + 1. Aquí el valor es 10, y la condición, esta vez sí, deviene en False... y el bucle se detiene.
Digamos que aquí tenemos una descripción o lectura natural, y esperamos que comprensible, de lo que hace el bucle while tomando como base el ejemplo anterior: partiendo de que el valor inicial de 'num' es 0, mientras que el valor de 'num' sea menor que 10, seguimos sumando el entero 1 a cada valor consecutivamente hasta que el valor de 'num' sea igual a 10 (num = 10), lo que suscita la ruptura (break) del programa.
Vamos con otro ejemplo sencillo de uso de while.



También podemos añadir la sentencia not, como en el caso de if, a nuestra sintaxis while:


Y puesto que le hemos cogido el gustillo a los ejemplos vamos con uno que resulta todo un clásico, un modelo recurrente en casi todos los manuales dedicados a Python cuando se ejemplariza el bucle while: la sucesión de Fibonacci. ¡Olé!

   
   La  llamada "sucesión de Fibonacci", mal llamada "secuencia"en algunos sitios, fue descrita por el matemático italiano Leonardo de Pisa, conocido como Fibonacci y de aquí el intitulado de la sucesión, allá por el siglo XIII, y consiste en una serie infinita de números naturales comenzando con 1 y 1 y, a partir de este último, se establece una relación de recurrencia donde cada término es la suma de los dos anteriores:1,  1 (0 + 1), 2 (1 + 1), 3 (1 + 2). 5 (2 + 3), 8 (3 + 5), 13 (5 + 8), 21 (8 + 13), 34 (13 + 21), 55 (21 + 34),...
¡Buff! Me he cansado ya de ladrar: con 55 ya tengo suficiente.
¡Hasta la próxima!







Estudiemos el caso: en 1, en nuestra primera instrucción, creamos dos variables de cabecera mediante asignación simplificada, ahorrando líneas de código usando a y b como nombres de identificadores  a las que asignamos, respectivamente, los valores iniciales 0 y 1. Esto es así porque la sucesión de Fibonacci comienza con dos números enteros: 1 y 1.
Seguidamente, recurrimos en 2. al bucle while y creamos la condición pertinente, b < 100, entre los paréntesis, y completamos con los dos puntos, dado que el bloque de código del bucle debe escribirse indentado.
Ahora procedemos a introducir las declaraciones: en 3. llamamos a la función print() y le pasamos tres parámetros, como ya sabemos de ejemplos anteriores, convenientemente separados por sendas comas. En primer lugar, el valor de la variable b, a continuación una string para poner una coma entre los valores y dejar un espacio en blanco (whitespace), por cuestiones estéticas y para facilitar la lectura "y no se nos arrejunten las cabras" y, finalmente, el operador end="" para evitar que Python nos devuelva un resultado iterado, en formato columna que es el establecido por defecto, y nos lo muestre en línea. 
En 4. introducimos la declaración clave: a, b = b, a + b. De nuevo recurrimos a nuestras variables de cabecera, tal y como ocurrió en el ejemplo anterior, y modificamos sus valores de partida. Ahora, tras la primera iteración de while, a valdrá lo que valga b, y b valdrá el resultado de sumar el valor de a y el valor de b: 2ª iteración => 0 + 1 = 1; 3ª iteración => 1, (1 + 1);  4ª iteración => 2, ( 1 + 2); 5ª iteración => 3, (2 + 3);  6ª iteración => 5, (3 + 5); etc.
Y así sucesivamente mientras b sea menor que 100. Cuando la condición no pueda cumplirse, es decir, devenga False, dejará de ejecutarse el programa.
La "sucesión de Fibonacci", ya que estamos, no es una simple 'boutade' tiene su valor matemático y está presente en la Naturaleza: la disposición de las ramas de los árboles en torno al tronco, la disposición de las hojas en el tallo de muchas plantas, en la estructura en espiral de algunas conchas de animales, en los vórtices de los huracanes, en la disposición en espiral de los brazos de las galaxias, y en muchísimos más ejemplos.
Sorprendente. No está mal saberlo.

VISTA DEL VALLE DE TAGANANA Y DE LA PARTE ALTA DEL PUEBLO DESDE LA DORSAL. ANAGA, NORESTE DE TENERIFE.

El bucle o sentencia while  soporta también la cláusula else, que es opcional, de acuerdo a la sintaxis:

                                                                                     WHILE (CONDICIÓN BOOLEANA):
                                                                                                 BLOQUE_DE_CÓDIGO-WHILE
                                                                                     ELSE:
                                                                                                 BLOQUE_DE_CÓDIGO-ELSE

Como ya sabemos, mientras la condición establecida en la expresión sea True, la declaración o declaraciones de while, su bloque de código asociado, si lo preferimos así, continuará ejecutándose con cada iteración hasta que la condición devenga False, en cuyo caso se rompe el bucle y, en el supuesto de que hubiéramos dispuesto una cláusula else, se ejecutará su declaración (es) o bloque de código asociado. Mostramos un ejemplo a continuación.


Sin embargo, a todas éstas, debemos tener presente que el recurso a la cláusula else implica que si el bucle while se ejecuta y finaliza correctamente, el bloque de código asociado a la misma siempre se ejecuta, salvo en estos tres supuestos:

  1. Si el bucle finaliza abruptamente por una sentencia break.
  2. Si el bucle finaliza por una sentencia return, si está integrado en un método o función.
  3. Si se lanza una excepción
Veamos un ejemplo, ya que la hemos nombrado, de uso del bucle con la sentencia break:



Por último, el bucle while puede establecer un límite en una iteración llevada a cabo por un bucle for/in para evitar que, si no obtenemos un resultado, dicho bucle for/in continúe iterando hasta el final de la secuencia. Imaginemos que circulamos por una autopista y nuestra intención es tomar el primer desvío que nos lleve a una localidad o espacio determinado. Vamos dejando atrás diferentes desvíos que nos señalan distintas ubicaciones que no son de nuestro interés hasta que encontramos uno que indica nuestro lugar de destino. A pesar de que podemos encontrar nuevos lugares llamativos a lo largo de nuestra ruta, nos decidimos por éste en concreto y ya no tenemos necesidad de continuar circulando por la autopista: es como si hiciéramos un stop y bifurcáramos saliéndonos de la dirección y sentido de la autopista. Aquí nuestro stop es la sentencia while.
Aunque lo veremos a continuación, podemos adelantar que el bucle for/in recorre toda la secuencia de principio a fin, a menos que acotemos una subsecuencia con el concurso de la función range(), iterando ítem por ítem en orden a sus índices respectivos de izquierda a derecha, esto es, de menor a mayor: primero secuencia[0], luego secuencia[1], luego secuencia[2] y así sucesivamente hasta el final. Sin embargo, el bucle while necesita que le indiquemos con qué índice comienza a aplicar la condición y hasta que índice puede llegar.
Y un aspecto fundamental: el bucle while es DINÁMICO, esto es, que no opera sobre una secuencia de datos dada, como sí lo hace for/in sino que lo hace sobre una secuencia que se va generando progresivamente mientras el resultado de la evaluación de la sentencia while continúe siendo True.
Resumiendo:

  • for/in: el bucle (loop) recorre una secuencia mediante una variable que ejerce como controlador (for item in secuencia: → item es la variable controladora) sobre una secuencia de tamaño conocido y/o cerrado (podemos no conocer la secuencia de antemano, por ejemplo, una lista que vaya almacenando durante un tiempo determinado todas las palabras que se nos vayan ocurriendo a lo largo de un minuto que empiecen por "z". Se nos pueden ocurrir 3, 10, 20, o más o menos, pero una lista SIEMPRE tiene un principio, lista[0], y un final, lista[-1])
  • while: la "variable controladora" es, en este caso, una condición lógica en tanto que, si bien conocemos la condición que nos hace salir del bucle, desconocemos a priori el número de elementos sobre los que se puede iterar.

Acabamos recordando que la estructura sintáctica de while es muy similar a la del condicional if/elif/else: se apoya en un análisis booleano, igual que if, donde la declaración se ejecuta mientras while devenga True. Sin embargo, la diferencia estriba en que en el caso de if, cuando el resultado es True, no continúa con el flujo del código y bifurca, mientras que while regresa a la cabeza y reevalúa nuevamente la expresión una y otra vez hasta que devenga False.
Observemos todavía un par de ejemplos más.




       ADVERTENCIA: POR LA FORMA TAN PECULIAR QUE PYTHON TIENE DE TRATAR A LOS NÚMERO DECIMALES, float, NI SE NOS OCURRA ESTABLECER CONDICIONES CON ESTE TIPO DE DATOS, YA QUE CORREMOS UN RIESGO SERIO DE ENTRAR EN UN BUCLE INFINITO.



No nos resistimos a incluir un par de ejemplos más de uso del bucle while, esta vez, en situaciones de codificación, por así decirlo, más comunes, como por ejemplo, como verificadores de una condición:



      BUCLE While True:


      Contamos con un recurso peculiar dentro del bucle: while True. Si nos fijamos, su lectura es muy simple: "mientras sea verdad...". ¿Qué quiere decir ésto? Muy sencillo: nuestro flamante bucle while continuará indefinidamente haciendo lo que sabe hacer, es decir, ITERAR, bien a lo largo de una secuencia o bien en el marco de un proceso de código, evaluando continuamente mientras la condición propuesta devenga verdadera, es decir, sea True. La diferencia es de tipo sintáctica: mientras que hasta ahora hemos incorporado la condición detrás del bucle while en el momento de la formulación, como por ejemplo, while not "." in s, en la captura anterior, en el caso de while True la condición se establece después. Esta condición posterior se conoce como condición de salida.
El quid del asunto estriba en que while True ejecutará la iteración indefinidamente mientras que la condición devenga verdadera, y claro: toda condición de salida, por su propia naturaleza  y por definición, SIEMPRE va a ser evaluada como True, por lo que obtendremos un bucle infinito como un castillo. Todo depende, pues, que la condición de salida sea dinámica y, en algún momento, devenga o pueda devenir en False, rompiendo el ciclo, por ejemplo, cuando nosotros mismos como usuarios interrumpamos la ejecución del programa.
Así pues, conviene siempre finalizar con una sentencia break toda llamada a while True por la cuenta que nos trae.


¡Ay si nos olvidamos de break... !


Su uso suele restringirse para todas aquéllas acciones que queremos que cumpla siempre una condición, como por ejemplo, mientras un archivo de texto esté abierto (while True: open("*.txt")) que nos imprima en pantalla el número de milisegundos que permanece en esa condición.


Por el mismo motivo, un bucle while False, aunque sintácticamente es lícito, resulta una soberana tontería, dado que si toda condición de salida es True (verdadera) por definición, el bucle while False no se ejecutaría nunca.




T4. BLOQUE DE EJERCICIOS 8. SOLUCIONES.

SISTEMA DE CUEVAS Y EROSIÓN PRODUCIDA POR LAS ESCORRENTÍAS EN LAS LADERAS DEL BARRANCO DE VALLESECO, SUR DE ANAGA, NORESTE DE TENERIFE.




No hay comentarios:

Publicar un comentario