¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
  1. Libros
  2. Python
  3. Bucles, listas y entradas
Extrait - Python Aprenda a programar proyectos lúdicos
Extractos del libro
Python Aprenda a programar proyectos lúdicos Volver a la página de compra del libro

Bucles, listas y entradas-salidas

Introducción

En este capítulo, presentamos los elementos siguientes:

  • Bucles y condiciones anidadas, que permiten que aparezcan estructuras complejas en la cadena de tratamiento.

  • Listas, que permiten almacenar varias piezas de información y eliminar o agregar información dinámicamente.

  • Administración de archivos, que permite leer y escribir información en el disco.

Las condiciones anidadas

1. La noción de bloques anidados

La ramificación de una instrucción if y el cuerpo del bucle de una instrucción for representan una noción similar, que agrupamos bajo el término general de subbloque de código. Los subbloques, ya provengan de una ramificación o del cuerpo de un bucle, tienen la capacidad de contener otros subbloques. Se encajan naturalmente, como las muñecas rusas.

La diferencia entre las muñecas rusas y el código de un programa es que solo existe una inclusión por cada nivel: cada muñeca solo puede contener otra muñeca de menor tamaño, que a su vez también podrá contener una sola muñeca.

images/04RI00.PNG

Muñecas rusas anidadas

En el lenguaje Python, un bloque corresponde a líneas sucesivas de código con el mismo nivel de indentación. Dentro de esas líneas puede haber otras líneas de código de nivel de indentación más bajo. Estas líneas describen los subbloques relativos al bloque actual. Las instrucciones: print("hello") o a = b + 1 no generan la aparición de subbloques en las líneas del código. Para crear un anidamiento, tiene que usar un bucle for o una condición if. En los últimos niveles de inclusión, encontramos bloques de terminales que solo contienen instrucciones simples sin bucle y sin condiciones.

La indentación natural del lenguaje Python resalta el nivel de inclusión en el que se encuentra cada línea de código. Analicemos un ejemplo para mostrar la jerarquía entre los bloques:

images/RI03_001.png

El bloque principal contiene tres instrucciones, de las cuales dos son bucles for que crean dos subbloques B y F de nivel 2 y una llamada a la función print(). Los bloques terminales D, E y H no contienen ningún subbloque porque no contienen ninguna instrucción if/for. Podemos ver que se encuentran en niveles diferentes. Esto es normal; el nivel de un bloque terminal depende de los bloques anteriores. De esta manera, en un programa, los bloques terminales no están todos al mismo nivel. El bloque B contiene tres instrucciones, incluido un bucle for lo que crea un subbloque C. El bloque C contiene una instrucción if/else que genera dos subbloques suplementarios. El bloque F contiene tres instrucciones, incluyendo un bucle...

Listas

Podríamos ocupar varias páginas con la explicación de las listas, pero es un objeto muy intuitivo que preferimos presentar a través de ejemplos.

Si queremos almacenar todos los nombres de los alumnos de una clase, las temperaturas del último mes o las matrículas de una flota de vehículos de alquiler, necesitamos una estructura que nos permita almacenar varios datos.

Esta estructura también debe poder evolucionar con el tiempo porque puede llegar un nuevo estudiante; entonces habrá que añadir su nombre a la lista. Otro estudiante puede mudarse, y en este caso, habría que quitar su nombre de la lista. Podríamos cometer un error al introducir los datos y un nombre podría estar mal escrito, por lo que deberíamos ser capaces de modificarlo sin tocar los otros nombres presentes. Las listas están hechas para ofrecer todas estas características que presentaremos a continuación.

1. Crear una lista

Creamos una lista vacía escribiendo un símbolo de corchete de apertura seguido de un símbolo de corchete de cierre. Para crear una lista a partir de una muestra de valores, separamos estos diferentes valores con comas y los rodeamos con un par de corchetes. He aquí un ejemplo:

L = []                   # Lista vacía 
M = [ 11, 12, 15]        # Lista con tres elementos 
print(M)                 # ¡La función print acepta las listas! 
>> [11, 12, 15] 

En Mac, los símbolos de corchete no están presentes en el teclado. Debe utilizar una combinación de teclas: [Alt] [Mayús] (.

El lenguaje Python es muy flexible: le permitirá almacenar valores de cualquier tipo en una sola lista. Así, puede escribir L = [ "Hola",7, 3.14]. El hecho de que esto sea posible no significa necesariamente que sea una buena idea. De hecho, esta práctica no se aconseja en absoluto porque es la mejor manera de tener problemas. De todos modos, si crea una lista que contenga tipos heterogéneos, a no ser que quiera obtener solo una visualización, en los demás casos, tendrá que tratar cada elemento por separado...

El bucle while y las entradas-salidas en archivos

1. El bucle while

Vamos a presentar la estructura de bucle utilizando la palabra clave while. Al igual que para la condición if, el bucle while requiere una condición que indique si su subbloque tiene que volver a ejecutarse o no. Mientras la condición sea cierta, su subbloque se ejecutará. Veamos un ejemplo:

Abrir un archivo de texto 
mientras (no se alcance el final del archivo): 
 Cargar la siguiente línea en el archivo y mostrarlo 
Cerrar el archivo 

Este enfoque le permite examinar un archivo completo y procesar la información que contiene. No es posible saber cuántas líneas hay que leer en un archivo. Por lo tanto, no se puede usar un bucle for con índice. Es verdad que se conoce el tamaño del archivo con antelación, pero no podemos deducir el número de líneas. El bucle while se adapta muy bien a estos casos.

Siempre se puede cargar un archivo completo en una cadena de caracteres y luego pasar por esa cadena con un bucle for con subíndice. Pero este enfoque es un truco que puede resultar peligroso cuando el tamaño del archivo que se tenga que tratar sea importante.

2. Nunca remplazar un bucle for con un bucle while

Podemos escribir el siguiente código:

K = 10 
while K < 13 : 
     print(K) 
     K += 1 
print("Terminado") 

Esta sintaxis es correcta. Sin embargo, es torpe. Los tres elementos esenciales de un bucle for están presentes: la inicialización del índice inicial con K=10, el incremento al final del bloque con K += 1 y el índice final proveniente de la condición K<13. En este caso, debemos preferir el uso de un bucle for y escribir: 

for i in range(10,13): 
   print(K) 
print("Terminado") 

¿Por qué? Finalmente, ambas sintaxis son correctas y ambos ejemplos producen exactamente el mismo resultado. Hay una diferencia, sin embargo, no muy evidente aquí. Supongamos que, en el ejemplo del while, el cuerpo del bucle tuviera 50 líneas. El incremento K +=1 estaría entonces muy lejos de la instrucción while. Además, también puede haber varias líneas entre la asignación K=10 y la instrucción while. En esta configuración, los tres...

Listas de caracteres y cadenas

1. Conversión entre listas y cadenas

El método para guardar información en un archivo que utiliza las funciones write() y readline() no permite guardar estructuras más complejas, como las listas. Nos gustaría poder escribir: f.write([4,5,6]), pero esto no es posible. Para empezar, la función write() no acepta números. Podríamos encontrar una solución convirtiendo cada número en una cadena de texto con la función str() antes de la escritura y también podríamos usar la función int() para convertir la cadena correspondiente en un número durante la lectura.

Sin embargo, de por sí ya hay mucho que escribir en un programa y, cuando los datos comienzan a ser complejos y numerosos, tenemos tendencia a querer que las cosas sucedan de manera simple y rápida. Así, cuando tenemos una lista, por ejemplo, nos gustaría tener una función que convirtiera su contenido, cualquiera que sea, es decir, tanto cadenas como números, en una cadena de caracteres. Además, esta función debería gestionar automáticamente la cantidad de elementos presentes en la lista, así como el caso particular de las listas vacías. Y, como suele ser el caso en Python, ¡esto ya existe! El paquete json nos proporciona métodos para compactar cualquier dato en una cadena (los profesionales...

Mensajes de error

1. Errores de corchetes

Para acceder a un elemento de una lista, utilizamos un par de corchetes que contienen un subíndice entero. Esta sintaxis puede ocasionar varios errores:

T = [3,4,5] 
T(4)= 5 

Como posiblemente haya notado, los corchetes han sido remplazados inadvertidamente por un par de paréntesis. El error asociado es incomprensible:

T(4) = 5 
SyntaxError: can't assign to function call 

De hecho, tan pronto como el intérprete ve un par de paréntesis después de un identificador, aquí T, entiende que estamos tratando de llamar a una función denominada T (ver el capítulo Funciones). Una llamada a una función (function call) no puede aparecer a la izquierda de un símbolo de asignación = porque se espera una variable. El término «asignación» se traduce como «assignment» en inglés. Recibiremos un el mensaje de error: «can’t assign to function call».

2. Errores de índice

Para acceder al elemento de una lista, se debe utilizar un valor entero. Veamos qué pasa en el caso contrario:

L = [4,5,6] 
k = 1,3 
print(L[k]) 

El mensaje es claro y le explica el problema:

print(L[k]) 
TypeError: list indices must be integers or slices, not float 

En inglés, el término «slice» se refiere a un rango de valores. Por lo tanto, este mensaje significa que el índice...

Algunos trucos

Para hacer ejercicios de entrenamiento más variados, utilizaremos nuevos operadores e instrucciones. Se los presentamos porque, en cualquier caso, forman parte de los clásicos de la programación.

1. Parámetros opcionales de la función print

Cuando la función print() recibe varios argumentos, como print("uno","dos"), los muestra separados por un espacio. Ya reciba uno o más argumentos, o incluso ninguno, esta función coloca el cursor en la siguiente línea produciendo un salto de línea.

Se pueden modificar ambos comportamientos usando parámetros opcionales:

  • El parámetro sep se utiliza para cambiar el separador insertado entre los argumentos de la función print(). Por defecto, están separados por un espacio. 

  • El parámetro end permite definir la cadena que se mostrará después de que se termine la visualización de los argumentos. Esto le permite esquivar el salto de línea automático que proporciona una cadena vacía como argumento. Por defecto, el parámetro end corresponde al carácter especial /n, que codifica un salto de línea.

He aquí un ejemplo:

print("Búho","Piedra") 
print("Foo",end="##",sep="AA") 
print("Bar","Baz","Xyzzy",end="KK",sep="BB") 
print("============") 
 
>> Búho Piedra 
>> Foo##BarBBBazBBXyzzyKK============ 

El primer print() tiene dos argumentos. Por lo tanto, las dos cadenas "Búho" y "Piedra" están...

Ejercicios de aplicación

1. Bucles anidados I

Indique los valores que muestra el siguiente programa:

for i in range(3) : 
 for j in range(7): 
   print(i+j,end="") 
 print() 

Corrección guiada:

El bloque principal contiene un bucle for i; este índice recorrerá los valores 0, 1 y 2. El bucle for i define un subbloque que contiene un bucle for j y una instrucción print(). Cuando entramos en este subbloque, el valor del índice i es fijo. Por ejemplo, en la primera ejecución es 0. El bucle for j realiza una serie de visualizaciones para j que van de 0 a 6. Como el salto de línea de la instrucción print() está deshabilitado, los números se muestran uno detrás de otro. Una vez que se complete el bucle for j, pasamos a la siguiente instrucción en el mismo nivel, es decir, la instrucción print(), que no muestra nada, pero produce un salto de línea. Así, obtenemos:

>> 0123456 

Después de la instrucción print(), no hay más instrucciones. Así que volvemos al bucle for i superior. El índice i cambia al valor 1 y el subbloque que contiene el bucle for j se ejecuta con este nuevo valor. La mecánica dentro de este bloque sigue siendo la misma; solo cambia el valor mostrado, porque esta vez i es 1. Esto nos da la siguiente pantalla:

>> 123457 

Una vez terminado el subbloque, volvemos al bucle for i para pasar al último valor que vamos a estudiar: 2. El subbloque se ejecuta con este valor y produce la siguiente visualización:

>> 234578 

Una vez que se termina el subbloque, volvemos al bucle for i. Como no hay más índices que recorrer, el bucle for i ha terminado. Pasamos a la siguiente instrucción en el mismo nivel. Como no hay ninguna, el programa ha terminado.

He aquí el resultado final:

>> 0123456 
>> 1234567 
>> 2345678 

2. Bucles anidados II

Indique los valores que muestra el siguiente programa:

for i in range(1,7) : 
   for j in range(i): 
       print("#",end="") 
   print() 

Corrección guiada:

La estructura es parecida a la del ejercicio anterior. Sin embargo, el rango de valores del segundo bucle depende del índice del primer bucle, lo que complica un poco las cosas....

Ejercicios de entrenamiento

1. Calcular la suma de los elementos de una lista images/etoile.png

La corrección de este ejercicio se puede descargar desde la página web de la editorial. Para una lista de enteros, dé la suma de sus elementos. Para realizar este tipo de cálculo, es necesario utilizar una variable adicional que acumule los valores en la lista durante su recorrido. Recuerde que tiene que inicializar esta variable correctamente. La lista tiene cualquier tamaño, téngalo en cuenta a la hora de escribir el programa.

2. Repartir los números pares e impares en dos listas images/etoile.png

La corrección de este ejercicio se puede descargar desde la página web de la editorial. Partiendo de una lista de enteros dada, divida estos elementos en una lista IMPAR que contenga los números impares y una lista PAR que contenga los números pares. Muestre el resultado. Para comprobar si un número k es par, la expresión k%2 le será de utilidad.

3. Contar las apariciones de cada número en una lista images/etoile.png

La corrección de este ejercicio se puede descargar desde la página web de la editorial. Para una lista de enteros entre 0 y 9, cuente el número de apariciones de cada número en la lista. Así, para la lista L = [2, 5, 2, 5, 5, 8], tenemos dos apariciones del número 2, tres apariciones del número 5 y el número 8 aparece una vez. Le proponemos dos enfoques; puede usar uno u otro:

  • Primero, realice un bucle principal en los números que está buscando. A continuación, haga un bucle anidado que cuente el número de apariciones de ese número en la lista. Si aparece al menos una vez, muestre su número de apariciones.

  • Inicialice una lista con diez valores 0, con la sintaxis L=[0]*10. Cada casilla de esta lista se utiliza para contar el número de apariciones de cada valor: 0, 1,..., 9. A continuación, cree un bucle que recorra la lista. Cada vez que lea un valor v, aumente el contador correspondiente. Una vez que se haya recorrido la lista, recorra la lista de recuentos y muestre los números que hayan aparecido al menos una vez.

4. Mostrar una textura de malla images/etoile.png

La corrección de este ejercicio se puede descargar desde la página web de la editorial. Le proponemos hacer que aparezca la siguiente textura compuesta por caracteres X y espacios:...

Proyectos

1. Resolver un criptoritmo images/etoile.pngimages/etoile.png

La corrección de este proyecto está disponible para su descarga en el sitio web de la editorial. Un criptoritmo es una secuencia de operaciones aritméticas entre palabras en las que cada letra corresponde a un número. La codificación debe respetar las siguientes reglas: la misma letra siempre representa el mismo número, dos letras diferentes representan dos dígitos diferentes. El objetivo del juego es encontrar una coincidencia entre letras y números que dé un resultado exacto. He aquí un ejemplo:

 

 

U

N

O

 

U -} 1 N -} 3

 

 

1

3

7

+

 

U

N

O

 

O -} 7 D -} 2

 

 

1

3

7

 

--

--

--

-

 

S -} 4

 

--

--

--

--

 

 

D

O

S

 

 

 

 

2

7

4

Le proponemos escribir un programa para resolver el criptoritmo: DOS + DOS + SEIS = DIEZ.

Consejo:

  • Cree variables para cada letra que se llamen como la misma letra, por ejemplo.

  • Tiene un total de seis letras: D, O, S, E, I, Z, y debe probar para cada una de ellas los diez números posibles. Puede optimizar un poco para la letra D porque no puede ser igual a cero, ya que está al principio del número. De esta manera, debe generar un bucle for para cada letra y anidar seis bucles for.

  • Recuerde comprobar que todas las letras corresponden a números diferentes. Para ello, no existe un método elegante en este nivel; será necesario realizar las quince pruebas necesarias.

  • Una vez que se posicione el valor de cada variable, puede calcular fácilmente el valor de DIEZ haciendo D * 1000 + I * 100 + E * 10 + Z.

Encontrará algunos ejemplos de criptoritmos en la página web de Wikipedia. ¡Ahora podrá resolverlos todos!

Corrección:

for D in range(1,10) : 
 for O in range(10) : 
  for S in range(10) : 
   for E in range(10) : 
    for I in range(10) : 
     for Z in range(10) : 
      dif1 = D != O and D != S and D != E and D != I and D!=Z 
      dif2 = O != S and O != E and O != I and O != Z 
      dif3 = S != E and S != I and S != Z 
      dif4 = E != I and E != Z and I != Z 
      if...