Ej. 20 : Trabajando con funciones y ficheros…

Las funciones y los ficheros pueden trabajar juntos para hacer cosas útiles como ésta:

Ej.20 - Programa Ej.20 - Terminal

Éste ejercicicio me ha gustado mucho.

Es interesante ver cómo podemos insertar contenido del fichero txt con frases del programa.

Al principio no entendía mucho porque lo estaba mirando sin la ejecución y estaba pensando sólo en abstracto, olvidándome de que va incorporando las líneas del texto. De eso va el ejercicio, de cruzar ambos ficheros.

ALGUNAS PREGUNTAS

P: ¿Qué es f en print_all y otras funciones?

R: La f es una variable como las usadas en el Ejercicio 18, aunque en éste caso es un archivo. En Python, un fichero es como un reproductor de DVD. Tiene una «cabeza lectora» para poder ir leyendo y saltando a diferentes posiciones del fichero. Cada vez que hago f.seek(0)  estoy moviéndome al inicio del fichero. Cada vez que hago f.readline(), estoy leyendo una línea del fichero y moviendo la cabeza lectora a la derecha de \n, que es el final de ésa línea (salto de línea). Lo seguiré explicando cuando avance.

P: ¿Por qué hay líneas en blanco en el fichero?

R: Buena pregunta. Yo también me la hice al principio. Como hice en el ejercicio 10 y el ejercicio 16, la función readline() devuelve el \n que hay al final de cada línea. Ésto significa que estamos mostrando en pantalla éste carácter (salto de línea), además del \n propio de print. Para que no ocurra hay que añadir el carácter , (coma) al final de print, así no motrará en pantalla su propio \n.

P: Mmmm. Entonces, ¿por qué seek(0) no establece el valor de current_line a cero?

R: En primer lugar, seek(0) es una función que trabaja a nivel de bytes, no líneas. Así que con eso saltamos al byte 0 (el primer byte) del fichero. En segundo lugar, current_line es sólo una variable y no está conectada de ninguna forma con el fichero. Hay que incrementar el valor manualmente.

P: Pero entonces, ¿cómo sabe readline() dónde está cada línea?

R: Dentro de readline() hay un cógigo que escanea cada byte del fichero hasta encontrar el carácter /n, entonces para de leer y devuelve lo que ha encontrado hasta ahí. El fichero f es responsable de mantener la posición actual en el fichero después de cada llamada a readline().

P: ¿Qué es +=?

R: Es un tipo de contracción de los operadores. Por ejemplo, decir que x += y es decir lo mismo que x = x + y.

En éste caso podríamos escribir: current_line += 1  que sería lo mismo que decir current_line = current_line + 1

Con todo lo anterior, ahora si, comento el código.

Ej.20 - Programa comentado

Ej. 19 : Relacionando (o no) funciones y variables…

Voy a reforzar un concepto relativamente importante: las variables en las funciones no están conectadas al resto de las variables del resto del programa.

Un ejemplo:

Ej. 19 Programa

Éste código muestra todas las formas diferentes de pasar valores a la función cheese_and_crackers. Podemos pasar números, ecuaciones matemáticas, y combinar ecuaciones matemáticas con variables.

En cierto modo, los argumentos de una función son algo así como el carácter = cuando creamos una variable. De hecho, si puedo usar = con algo, normalmente puedo pasarlo a una función como un argumento.

Ejecuto el programa y …  Ej.19 Terminal

A ver si lo he entendido…

Voy comparando el programa con lo que ejecuta en el terminal, y si coincide con lo que creía yo que deberia de salir en pantalla antes de ejecutarlo.

Para empezar me llama la atención que empiece a ejecutar a partir de la línea 8 del código del programa y luego vuelva atrás, pero lo entiendo. Al fin y al cabo está dando valores a la función cheese_and_crackers que de la línea 1 a la 5 está definida, pero sin valores específicos.

En el resto de párrafos se repite lo mismo, pero cambiando los valores y mostrando las 4 frases del principio, pero con los valores cambiados y las modificaciones añadidas que se van proponiendo.

En fin. Si. En principio sigue siendo bastante intuitivo.

Lo comento más…

Ej. 19 Programa COMENTADO

ALGUNAS PREGUNTAS

P: ¿Y si quiero preguntar al usuario por el número de cheese y crackers?

R: Sólo necesito usar int para convertir lo que se obtiene de raw_input().

P: ¿Creando las variables en las líneas 13 y 14 cambian las variables en la función?

R: No. Éstas variables están separadas y «viven» fuera de la función. Son pasadas por parámetro a la función y se crea una versión temporal sólo para ejecutarla. Cuando la función termina, éstas variables temporales dessaparecen y todo sigue funcionando como antes. Más adelante me quedará más claro.

P: ¿Es malo tener variables «globales» (como en la línea 13 y 14) con el mismo nombre que las variables de la función?

R: Si. Porque desde ese momento no podré estar segura de cuál estaré  hablando…pero a veces es necesario usar el mismo nombre o podría hacerlo sin querer. Un lío vamos. Así que en la medida de lo posible, debo evitarlo.

P: ¿Las líneas 12-19 sobrescriben la función cheese_and_crackers?

R: Para nada. Estoy llamándola. Básicamente es un salto temporal a la primera línea de la función, a continuación, después de la última línea de la función regresa. No estoy remplazando la función con cualquier cosa.

P: Mmmm. OK. Me he hecho la una pregunta parecida comentando el programa. Es lo de las variables globales de la pregunta anterior. Le daré otra vuelta.

P: ¿Hay un límite de número de argumentos que puede tener una función?

R: Interesante pregunta. Depende de la versión de Python y el el ordenador que tenga, pero ese límite es bastante generoso. Lo que pasa es que el límite PRÁCTICO es de 5 argumentos aproximadamente, a partir de aquí la función se vuelve «incómoda».

P: ¿Se puede llamar a una función desde dentro de otra función?

R: Si. Haré un juego que haga ésto más adelante.

Ej. 10 : Repasando…

En el Ej. 9 vi algunas cosas nuevas como dos formas para hacer una cadena en varias líneas. En la primera forma escribí el carácter \n  (barra invertida y n) entre el nombre de los meses. Lo que estos dos caracteres hacen es un salto de línea en el lugar de la cadena de caracteres donde están.

Hay muchas secuencias de escape. Hago un ejercicio y lo explico.

Ej10 Editor

Aquí se observa cómo el uso de triple comillas «»» que encapsula el texto en rojo de arriba, permite poner tantas líneas de textos como se quiera, ya que hace que funcione como una cadena de caracteres o string.

Ej10 Terminal

SECUENCIAS de ESCAPE

Ésta es la lista de todas las secuencias de escape que soporta Python.

Secuencia de Escape En pantalla… O lo que es lo mismo…
\\ \ Una única barra invertida
\’ Escape de comilla simple en una cadena
\” Escape de comilla doble en una cadena
\a BELL ASCII bell
\b BS ASCII retroceso
\f FF ASCII avance de página
\n LF ASCII linefeed o salto de línea
\N{name} Sólo Unicode Carácter name en la base de datos Unicode
\r CR ASCII retorno de carro
\t TAB ASCII tabulación horizontal
\uxxxx Sólo Unicode Carácter con 16-bits hexadecimal y valor xxxx
\Uxxxxxxxx Sólo Unicode Carácter con 32-bits hexadecimal y valor xxxxxxxx
\v \v ASCII tabulación vertical (VT)
\ooo oo Carácter con valor octal
\xhh hh Carácter con valor hexadecimal

Poco a poco iré haciendo ejemplos de todo y volveré sobre ésta tabla.

P: Relacionado con la práctica 3. ¿Qué significa «combinar» escapes y formatos?

R: Cada uno de éstos ejercicios se puede combinar con otros para resolver problemas. Partiendo de lo que sabes sobre cadenas con formato, puedes escribir un código nuevo que use las cadenas y, además, use las secuencias de escape que hemos visto en éste ejercicio.

P: Cuando uso %r ninguna secuencia de escape funciona.

R: El formato %r muestra en bruto los datos que escribí, lo que incluye las secuencias de escape tal cual. Use en su lugar %s. Recuerda siempre que %r es para depurar y %s para mostrar en pantalla.

P: Cuando esscribo // o / no funciona.

R: Ésto se debe a que usas la barra / en lugar de la barra invertida \. Son caracteres diferentes y hacen cosas diferentes.