Polifacetismo y productividad

Si eres una persona polifacética, hay una máxima con la que seguro habrás tenido que lidiar en ocasiones: quien mucho abarca poco aprieta. Puedes aceptar el mensaje negativo y limitante o puedes, simplemente, ignorarlo por ridículo.

¿Qué significa «abarcar»? ¿Qué es «apretar»? ¿Quién decide cuánto estás apretando? ¿Tú mismo o quizás los demás?

Si basas el concepto de ti mismo en la opinión de los demás, permíteme dudar de que seas alguien verdaderamente polifacético.

El polifacetismo es una forma de vida que requiere coherencia con nuestros anhelos más profundos y un conocimiento muy claro de nuestros valores y prioridades. ¿Quién puede conocerlos mejor que nosotros mismos para permitirse el lujo de juzgarnos?

Se dice de este tipo de personas que tienen dispersas y poco claras sus prioridades, cuando la realidad suele ser precisamente lo contrario. Detrás de cada polifacético hay alguien que vive el presente intensamente, siendo su prioridad máxima extraer la mayor cantidad de jugo a ese instante efímero. Y es tal la energía que son capaces de volcar en ese momento presente que la consecución de objetivos medibles, inherentes a la propia actividad, suele ser algo que cae por su propio peso, aunque no sea ese su leit motiv.

Existen distintos modos de polifacetismo dependiendo de la frecuencia con la que varía el foco principal de interés. En un extremo está el que se dedica en cuerpo y alma durante meses, o incluso años, a una determinada actividad; hasta que llega el día en que es sustituida por otra completamente distinta, haciendo que aquella espere turno pacientemente a que la pasión vuelva a recuperarla al primer plano. En el lado contrario está el que es capaz de desplazar el foco varias veces en el mismo día sin que se resienta un ápice el nivel de compromiso. No es nada sencillo lograr una abstracción completa ni realizar la transferencia de pasión de un campo a otro en tan corto espacio de tiempo. En sucesivos artículos mostrare algunas técnicas que ayudarán a lograrlo.

Un polifacético viaja donde la pasión le lleva. Es tan vasto el campo del conocimiento y tan breve la vida que es difícil resistirse a la tentación de querer probar cada fruta de ese campo.

¿Y tú, te consideras una persona polifacética? Seguro que lo eres aunque no te lo creas. Pregúntate cuáles son tus inquietudes y descubre tus múltiples facetas. Y ten el valor de experimentarlas sin miedo y con libertad, ajeno a cualquier juicio de valor, procedente de ti o de cualquier otro.

Déjate enamorar; solo entonces serás un verdadero polifacético.

Javier Montero Gabarró


http://elclubdelautodidacta.es/wp/2012/06/el-metodo-de-los-1000-maestros/


El texto de este artículo se encuentra sometido a una licencia Creative Commons del tipo CC-BY-NC-ND (reconocimiento, no comercial, sin obra derivada, 3.0 unported)


El Club del Autodidacta


Índice completo de los artículos de la categoría Productividad.

Python: Aprendiendo a escribir

Objetivo: aprender el modo que tiene Python de escribir texto en un fichero.

Si te has leído el anterior artículo de esta serie, probablemente habrás intuido la temática del artículo hoy: la escritura en ficheros de texto.

Todo comenzó un día de octubre, cuando un nuevo y sofisticado ente entró en escena:

fichero = open('pruebas.txt')

Esta instrucción creaba un nuevo objeto, una abstracción del fichero de texto real en disco, pruebas.txt, que nos permitía realizar operaciones de lectura sobre él.

En realidad, ese comando no es más que una forma simplificada de:

fichero = open('pruebas.txt', 'rt')

O incluso:

fichero = open('pruebas.txt', 'r')

Las letras entrecomilladas, como segundo parámetro de la función open(), indican el modo en que se abrirá el fichero. La r (de read) y la t (de text) hacen referencia a que se trata de un fichero de texto y que sólo realizaremos operaciones de lectura, no estando, por lo tanto, permitida su modificación.

Cuando no se especifica el modo de apertura, se presupone la opción por defecto, que es precisamente esta: texto y lectura.

Hoy vamos a realizar la operación inversa: la escritura de ficheros de texto. Para ello presentaremos un nuevo modo: ‘w’, forma simplificada de ‘wt’.

Introduce la siguiente instrucción en un intérprete interactivo:

>>> fichero = open('prueba2.txt', 'w')

Lo primero que debes saber del modo ‘w’ es el efecto de esta operación: si el fichero indicado no existe, lo creará (naturalmente, vacío), y si ya existe lo sobreescribirá, perdiendo su contenido (y dejándolo, por lo tanto, vacío también).

El tipo de objeto es el mismo que en el ejemplo del artículo anterior:

>>> type(fichero)
<class '_io.TextIOWrapper'>

Con la particularidad de que las operaciones de lectura no están permitidas:

>>> fichero.read()
Traceback (most recent call last):
  File "<pyshell#32>", line 1, in <module>
    fichero.read()
io.UnsupportedOperation: not readable

El modo ‘w’, de write, nos permite escribir en ese fichero. El método estándar para realizar esto es write():

>>> fichero.write('Serie: La casa de la pradera\nAño: ni lo recuerdo, \
yo era pequeño\n\n¿La repondrán? ')
81

He facilitado, entre comillas, un string con el texto que quiero introducir. Lo podría haber hecho línea a línea, con llamadas a write() sucesivas, pero he optado por incluirlo todo en uno solo. Observa que, para separar una línea de la siguiente necesito hacer uso del carácter de escape \n.

La barra \ que he escrito al final de la primera línea es para decirle al intérprete que voy a continuar en la siguiente línea, de modo que quede más presentable el código. No forma parte del string.

El método write() devuelve un número con el total de caracteres que han sido escritos, 81 en este caso.

Las escrituras sucesivas continúan justo en el punto donde terminó la última:

>>> fichero.write('Quién sabe.')
11

Comprobemos es aspecto de nuestro archivo de texto final. Para ello, primero hay que cerrar el fichero, indicando que hemos dejado de trabajar con él, liberando la memoria ocupada y haciendo que se vuelque la información efectivamente en el disco:

>>> fichero.close()

Este es el contenido de prueba2.txt tras estas operaciones:

Serie: La casa de la pradera
Año: ni lo recuerdo, yo era pequeño

¿La repondrán? Quién sabe.

La escritura puede ser, desde luego, en cualquier parte del fichero, no necesariamente a continuación de la última operación. Podemos desplazarnos a cualquier punto empleando el método seek() que presentamos brevemente en el último artículo. Veremos esto a su debido momento.

Una operación frecuente en el trabajo con ficheros en Python consiste en volcar a un archivo de texto el contenido de una secuencia. Considera, por ejemplo, la siguiente lista:

>>> a = ['Litio\n', 'Sodio\n', 'Potasio\n']

Nuestra misión consistirá en crear un fichero de texto en el que figure cada elemento en una línea diferente.

Con lo explicado hasta el momento tenemos recursos suficientes para resolvere el problema: realizamos una iteración sobre la lista escribiendo, en cada pasada, el elemento correspondiente:

>>> fichero = open('prueba2.txt', 'w')  #El fichero antiguo se perderá
>>> for elemento in a:
  fichero.write(elemento)

  
6
6
8
>>> fichero.close()

Los tres números devueltos por el intérprete de comandos son, como hemos dicho, el número de caracteres escritos tras cada operación. En un programa independiente no aparecerían.

El fichero prueba2.txt tiene el contenido buscado:

Litio
Sodio
Potasio

Cada elemento de la lista ya contenía el \n al final, de modo que la siguiente escritura quedaba preparada en el punto adecuado. En el caso de no fuera así deberías facilitarlo tú. Por ejemplo:

>>> b = ['Fluor', 'Cloro', 'Bromo', 'Iodo']
>>> fichero = open('prueba2.txt', 'w')
>>> for elemento in b:
  fichero.write(elemento + '\n')

  
6
6
6
5
>>> fichero.close()

El archivo final contiene cada elemento en una línea distinta, como puedes comprobar:

Fluor
Cloro
Bromo
Iodo

En lugar de

fichero.write(elemento + '\n')

podemos recurrir a la elegancia de una especificación de formato:

fichero.write('%s\n' % elemento)

Fino, ¿verdad?

Para mayor elegancia aún disponemos del método writelines(). ¿Recuerdas, en el artículo anterior, que usábamos readlines() para volcar un archivo de texto a una lista? Precisamente, writelines() hace justo lo contrario: descarga a fichero el contenido de la lista.

Volvamos a la lista de metales alcalinos, en la que cada elemento se finalizaba con \n:

>>> a
['Litio\n', 'Sodio\n', 'Potasio\n']

El método writelines() vuelca a un un archivo el contenido de una lista (o cualquier secuencia, en general). Cada elemento se escribe a continuación del anterior:

>>> fichero = open('prueba2.txt', 'w')
>>> fichero.writelines(a)
>>> fichero.close()

—-

Litio
Sodio
Potasio

La separación de líneas ha sido posible porque cada elemento de la lista contenía ya el \n final.

Esto es todo por hoy. Entendidas las técnicas básicas de lectura y escritura, estamos ya en condiciones de realizar operaciones más avanzadas.

Javier Montero Gabarró


Python: Aprendiendo a escribir


El texto de este artículo se encuentra sometido a una licencia Creative Commons del tipo CC-BY-NC-ND (reconocimiento, no comercial, sin obra derivada, 3.0 unported)


El Club del Autodidacta


Consulta el índice completo de artículos relacionados con Python.

Acordes en la guitarra (éramos pocos y parió la abuela)

Siempre me ilusiona escribir un artículo sobre un tema que aún no haya sido tratado en el blog. Mientras lo hago, no puedo evitar dejarme llevar por ensoñaciones pensando en todo lo que me gustaría decir a lo largo de la serie, los conceptos importantes que desearía ilustrar con claridad. Esto me resulta tremendamente motivante.

La realidad, desde luego, se aleja bastante de lo soñado: el tiempo es limitado y mis inquietudes son muchas. Aunque, por lo general, considero equilibrada la atención que le dedico al blog, escribiendo entre tres y cinco artículos nuevos por semana, a veces resulta claramente insuficiente para atender como se merece cada una de las áreas temáticas que en él se tratan.

Es, naturalmente, el precio a pagar y fue una decisión que tuve que meditar bien cuando opté por este modelo en lugar de por otro más especializado.

Ante todo, quería que fuera un reflejo de mi forma de ser. Me podría pasar la vida entera aprendiendo de todo, construyendo puzzles y disfrutando del placer de colocar cada pieza sin preocuparme si lo acabaré o no. Mi gran motor de motivación es, ante todo, intrínseco, más que la satisfacción de objetivos. El verdadero placer, cuando eres capaz de vivir el momento presente, se encuentra en el camino más que en la meta.

Cuando se es trabajador, disciplinado y perseverante, es fácil descubrir que todos estos puzzles comienzan a tomar forma casi sin pretenderlo, ejerciendo el hábito constante de colocar una pieza y luego otra.

No estoy diciendo que no haya que perseguir objetivos. Por supuesto que sí y son un elemento importante en la motivación. Forman parte de la naturaleza humana y gracias a ellos se perfila el camino que luego tendremos el placer de recorrer.

Sirva todo este rollo, que debería repetir cada vez que presentase una nueva serie de artículos, como justificación, porque probablemente no podré satisfacer tus expectativas como lector si esperas una mayor frecuencia de aparición de entradas sobre tu temática favorita.

Lo que si te puedo asegurar es que cada pieza individual es, por si sola, autosuficiente. Si la interrogas y la escuchas con atención establecerá conexiones con el resto de piezas que ya posees en tu puzzle. Si, tras su cuidadosa lectura, se te originan nuevas dudas (piezas que buscar), me sentiré orgulloso por haber cumplido mi principal cometido.

La serie que tengo el placer de presentarte se denomina Acordes en la guitarra, y es una conexión práctica, aplicada al instrumento, de los conceptos teóricos expuestos en la categoría Armonía.

No se limitará a una simple colección de posiciones a memorizar. Aprenderemos a construirlos en cualquier parte del mástil, las notas e intervalos que los definen, su función. El objetivo a perseguir es dotarte de herramientas para que, llegado el caso en el que necesites un determinado acorde y no recuerdes su montaje, puedas aprender a deducirlo por ti mismo en cuestión de segundos. Y el proceso inverso: reconocer de qué acorde se trata simplemente observando su forma.

Pero, ante todo, lo que se pretende es extender tu universo armónico, algo que te enriquecerá como intérprete, arreglista o compositor.

Podrás encontrar todos los artículos, a medida que los vaya escribiendo, tanto en la categoría Armonía como en Guitarra.

Nos vemos, con las reservas expuestas al principio, dentro de muy poco. Hoy debo dedicarme a la armonía de otro modo: ensayo con la banda.

Javier Montero Gabarró


http://elclubdelautodidacta.es/wp/2012/10/acordes-en-la-guitarra-eramos-pocos-y-pario-la-abuela/


El texto de este artículo se encuentra sometido a una licencia Creative Commons del tipo CC-BY-NC-ND (reconocimiento, no comercial, sin obra derivada, 3.0 unported)


El Club del Autodidacta


Índice de la categoría Guitarra.

Índice de la categoría Armonía.

Carrera Popular Macarena 2012 – Sevilla

Suena el despertador a las siete de la mañana y, sin cuestionármelo siquiera, pese a ser domingo, me incorporo con el mismo gesto rutinario de cada día. Me aseo, me visto y desayuno.

Mi atuendo es distinto al del resto de la semana. Llevo un pantalón de deporte corto, una camiseta y unas zapatillas deportivas. A las nueve y media dará comienzo la penúltima prueba del ciclo de carreras populares del IMD 2012, dedicada esta vez al distrito Macarena.

Lo que me resulta llamativo es lo rutinario del acto. Recuerdo el torrente de emociones previas a las primeras carreras. Me resultaba difícil conciliar el sueño por los nervios e incluso tenía pesadillas relacionadas con ellas. No he perdido un ápice de ilusión en todo este tiempo, pero la experiencia te hace vivir las cosas de otro modo.

El día anterior, lo típico ante este tipo de eventos. Por la mañana un entrenamiento suave en el gimnasio y 16 km de bicicleta para tonificar músculos y dejar el sistema cardiovascular preparado. He comprobado que un ejercicio aeróbico moderado el día previo a la carrera mejora mi rendimiento después.

Un buen plato de espaguetis para llenar los depósitos de glucógeno es algo que también me funciona, lo tengo más que demostrado. Diez kilómetros es una distancia lo suficientemente respetable como para no olvidar salir con las baterías completamente cargadas.

Para preparar el corazón para esfuerzos bruscos, nada mejor que una película de terror por la tarde, así que me fui al cine a ver Paranormal Activity 4, repleta de sobresaltos taquicárdicos que te hacen salir con el doble de canas que cuando entraste.

Es broma, naturalmente. La elección de esa película fue algo completamente circunstancial.

Por la noche, la pasta que sobró del mediodía y a descansar (relativamente temprano para ser sábado).

De modo que, fresco como una rosa, me coloco el dorsal (el mismo para todo el circuito popular del IMD), me echo crema protectora para el sol y antes de las ocho y media ya estoy dirigiéndome en bicicleta al Parque de Miraflores, lugar donde iniciará y concluirá la carrera.

Ya están colocados los pivotes que delimitan el trayecto y me llama la atención encontrarme con el cartel del kilómetro dos en la Carretera de Carmona, cuando supuestamente le correspondería uno propio del tramo final. Deduzco que el sentido de la carrera se ha invertido respecto al del año anterior.

Amarro la bicicleta a una señal de tráfico junto al parque y me pongo a calentar trotando con suavidad. En mis primeras carreras era algo reacio a «desperdiciar» energía calentando, temeroso de que pudiera necesitarla después, cuando precisamente ocurre justo lo contrario: no sólo te ayuda a prevenir lesiones, sino que además pone a tono tus sistemas energéticos.

Configuro a mi compañero virtual para que corra a 6’/Km (es decir, 10Km en una hora). Bastante conservador, pero lo considero apropiado y acorde con la intensidad y frecuencia de mis actuales entrenamientos. Mi objetivo, como siempre, será terminar por delante de él, aunque sólo sea un metro (al final, le sacaría 650 metros).

En efecto, tal como intuí, salimos directamente hacia la Carretera de Carmona, recorriendo el circuito en dirección contraria.

Me siento cómodo al ritmo que llevo. No voy a todo gas, pero sensiblemente más rápido que los 6’/Km a los que programé el GPS. No sé exactamente a cuánto voy, pues he elegido una visualización en la que únicamente figura la distancia que le saco al compañero virtual, que no hace otra cosa que aumentar durante toda la carrera.

No sólo estamos yendo en sentido contrario. Además, el trayecto es diferente. En el kilómetro 5’5, aproximadamente, volvemos a entrar en el parque, en el que recorreríamos los 4’5 Km restantes.

Entro en meta en 54:59, sobrado de energía, y con el convencimiento de que podría haber apretado si me lo hubiera propuesto.

Pero no había necesidad de dejarme la piel. ¿Acaso no he cumplido con mi objetivo sobradamente?

9.810 metros; 54:59; 5:36/Km

Javier Montero Gabarró


http://elclubdelautodidacta.es/wp/2012/10/carrera-popular-macarena-2012-sevilla/


Puedes consultar el índice completo de artículos pertenecientes a la categoría running.


El texto de este artículo se encuentra sometido a una licencia Creative Commons del tipo CC-BY-NC-ND (reconocimiento, no comercial, sin obra derivada, 3.0 unported)


El Club del Autodidacta

Pisando donde ya pisé

Si eres seguidor habitual del blog, bien porque entras directamente en la página, o porque estás subscrito al feed o por correo electrónico, posiblemente te habrás dado cuenta de que ha disminuido la frecuencia de aparición de nuevas entradas. El propio calendario que figura en el área lateral lo confirma con claridad.

No; ni me he cansado ni me he vuelto perezoso. No he dejado de escribir un solo día.

Lo que sucede es que estoy invirtiendo mucho tiempo revisando los artículos antiguos. Releo lo que escribí meses atrás y a menudo no me gusta lo que encuentro. Mi estilo de redaccion ha ido evolucionando (¡cómo no, son más de 400 artículos ya!) y me resisto a aceptar mucho de lo que en su día me pareció correcto. ¡Qué gran verdad eso de que a escribir se aprende escribiendo!

Por otro lado, hace un año pretendía publicar a diario, lo que provocaba que muchas entradas se realizaran precipitadamente, sin dedicar el tiempo suficiente a su revisión.

Me he encontrado incluso artículos que he tenido que reescribir completamente.

Los que ya están modificados se reconocen fácilmente: aparece como imagen la oveja responsable de su redacción, incluyen en la parte inferior un recordatorio del tipo de licencia Creative Commons y hacen mención a la fecha de su última modificación.

En el blog no hay indicio de este proceso de revisión. Sin embargo, envío notificaciones de cada actuación en la página de Facebook de El Club de el Autodidacta, por Twitter y en mi página personal de Google+. Las entradas se diferencian de las habituales porque incluyen el comentario REPOST REVISADO.

Sinceramente: ojalá dentro de un año me viera obligado a modificar los contenidos que hoy escribo. Sería señal de que habría aprendido mucho en el camino.

Javier Montero Gabarró

Python: Aprendiendo a leer

Objetivo: aproximación al trabajo con ficheros en Python, mostrando cómo leer el contenido de un archivo de texto.

Como programador, necesitas familiarizarte cuanto antes con el trabajo con ficheros. Con frecuencia tu aplicación deberá recuperar información de un fichero para su procesamiento, o bien almacenará en él el resultado de ese proceso. Es común también el intercambio de información con el exterior en ambos sentidos: la aplicación se nutre de datos externos almacenados en ficheros y genera información que se guarda nuevamente ellos después.

Nos aproximaremos al trabajo con ficheros en Python de un modo gradual y aprenderemos a realizar las tareas más típicas partiendo de lo más simple: la lectura de un archivo de texto.

Supongo que ya conoces la diferencia entre los ficheros de texto y los binarios. Expresada de un modo simple, los primeros pueden ser leídos empleando un editor de texto plano, como gedit en Linux o el bloc de notas de Windows. Más técnicamente, podríamos decir que los ficheros de texto mantienen una codificación estándar que permite la asociación de cada byte (o un grupo de ellos) con un determinado carácter de texto, mientras que en los binarios el significado de cada byte es determinado por la propia aplicación, pudiendo representar cualquier tipo de entidad.

Ya sabes que para Python todo son objetos y, naturalmente, los ficheros también. Para que podamos interactuar con un fichero, Python crea una abstracción, un objeto, a través del cual se nos ofrece una serie de métodos para que podamos trabajar con él. Hay métodos para leer, escribir o modificar el cursor (la posición en la que se realizará la lectura o escritura), por indicar algunos.

Lo primero que debemos aprender es a crear esa abstracción, el objeto sobre el cual trabajaremos para interacturar con el fichero físico real. Es lo que se conoce como abrir el fichero.

Para hacerlo disponemos de la función open(), que usaremos del siguiente modo:

nombre_del_objeto = open(fichero_real, modo_de_apertura)

nombre_del_objeto es el nombre con el que designaremos la abstracción que envolverá al fichero_real. Dependiendo del valor que indiquemos en modo_de_apertura Python construirá un tipo de objeto u otro y determinará qué tipo de operaciones podemos realizar con él.

Iremos conociendo los distintos modos en los sucesivos artículos, pero por el momento quédate con la idea de que, cuando no se especifica un modo, Python sobreentiende que se trata de un fichero tipo texto y que sólo vas a realizar operaciones de lectura. Esto es justo lo que pretendemos lograr hoy, ser capaces de leer el contenido de un archivo de texto.

Créate un fichero de pruebas y abre un intérprete de comandos en el mismo directorio.

En este ejemplo, he creado el fichero pruebas.txt, con el siguiente contenido:

Comienza el fichero con una mención a la casa de la pradera.
La segunda línea suele hallarse después de la primera.

Esta es la cuarta línea, en la tercera había una línea en blanco.
Es una verdadera lástima que esta sea la última línea.

Observa que se trata de un fichero de cinco líneas en el que he dejado la tercera expresamente en blanco.

Para leer el fichero, la primera acción a realizar es, como hemos visto, abrirlo:

>>> fichero = open('pruebas.txt')

He elegido como nombre del objeto, fichero, sin complicarme la vida más. Entre comillas, como argumento de la función open() figura el nombre del archivo. Si no se encontrase en el mismo directorio en el que hemos ejecutado Python, deberíamos especificar su path completo.

Recuerda lo dicho anteriormente: si no indicamos un segundo parámetro con el modo de apertura, se sobreentiende el siguiente: texto y lectura.

Si tienes curiosidad por saber qué tipo de objeto ha creado Python, pregúntaselo:

>>> type(fichero)
<class '_io.TextIOWrapper'>

Que es algo así como un «envoltorio de entrada y salida texto».

Existen diversas formas de leer el fichero. Una de ellas es aprovecharnos de una particularidad muy interesante: podemos iterar sobre un fichero de texto recorriéndolo línea a línea, de modo semejante al que iteramos recorriendo una lista de principio a fin con el bucle for.

Ensayemos lo siguiente:

>>> for linea in fichero:
  print(linea)

  
Comienza el fichero con una mención a la casa de la pradera.

La segunda línea suele hallarse después de la primera.

Esta es la cuarta línea, en la tercera había una línea en blanco.

Es una verdadera lástima que esta sea la última línea.

Salvo por el detalle de que ha intercalado una línea en blanco adicional entre cada línea, el resultado es bastante decente.

Enseguida veremos cómo solucionar esto, pero antes necesito que observes un comportamiento curioso.

Vamos a intentar iterar una segunda vez y veamos qué ocurre:

>>> for linea in fichero:
  print(linea)

  
>>> 

No ha devuelto absolutamente nada. La iteración está agotada.

Python, paralelamente al proceso de lectura, actualiza un cursor indicando cúal es el siguiente elemento a leer. Como ya ha llegado al final, un nuevo intento de lectura fracasa, pues no hay nada más que leer.

¿Significa esto que no podemos leer un fichero varias veces? En absoluto. Existe un método que nos permite mover el cursor de lectura al punto deseado.

>>> fichero.seek(0)
0

Esta instrucción nos posiciona nuevamente al comienzo del fichero (carácter en la posición 0). La trataremos con detalle en otro momento, pero por ahora es suficiente con que retengas este uso.

Ya estamos en condiciones de realizar una segunda lectura, pero esta vez lo haremos sin que se impriman las líneas en blanco adicionales.

¿A qué se debe que haya dos líneas en blanco?

Python distingue una línea de otra terminándola con el carácter de nueva línea (\n). Pero, además, la función print() agrega siempre, por defecto, otro carácter de fin de línea al final, de modo que cada impresión queda separada de la anterior en una línea diferente. Por eso encontramos los dos saltos de línea: el que trae cada línea propiamente dicha más el que agrega la función print().

Para esta segunda lectura vamos a modificar la función print(), agregando un parámetro con el carácter o caracteres que deseamos que agregue al final de cada impresión, en lugar de la opción por defecto, el salto de línea. Para indicar que no queremos que agregue nada, el uso de print() debe ser el siguiente:

print(linea, end='')

De modo que nuestra iteración por líneas ahora produciría el resultado deseado:

>>> for linea in fichero:
  print(linea, end='')

  
Comienza el fichero con una mención a la casa de la pradera.
La segunda línea suele hallarse después de la primera.

Esta es la cuarta línea, en la tercera había una línea en blanco.
Es una verdadera lástima que esta sea la última línea.

Voy a presentarte a continuación un método interesante que te permite leer el fichero de una sola vez: read().

Posiciónate de nuevo al comienzo del fichero, que habrá quedado exhausto tras la lectura anterior.

>>> fichero.seek(0)
0

Y ejecuta esta nueva instrucción:

>>> fichero.read()
'Comienza el fichero con una mención a la casa de la pradera.\nLa segunda línea suele hallarse después de la primera.\n\nEsta es la cuarta línea, en la tercera había una línea en blanco.\nEs una verdadera lástima que esta sea la última línea.\n'

Devuelve un string muy largo con el contenido del fichero (probablemente tendrás que usar la barra de desplazamiento al ver esto en el navegador, pues el contenido se muestra en una única línea).

Lo importante es que se aprecia bien la estructura del fichero, con los \n separando cada línea. Fíjate también en la línea en blanco, en la posición donde está el \n\n.

Naturalmente, esta salida la obtienes a través del intérprete interactivo. Si quieres ver el resultado en un programa tendrás que usar la función print() para mostrarla.

>>> fichero.seek(0)
0
>>> print(fichero.read())
Comienza el fichero con una mención a la casa de la pradera.
La segunda línea suele hallarse después de la primera.

Esta es la cuarta línea, en la tercera había una línea en blanco.
Es una verdadera lástima que esta sea la última línea.

Una lectura con read(), al igual que la iteración, deja exhausto el fichero, posicionando el cursor de lectura al final de todo:

>>> fichero.read()
''

Presta mucha atención a esto: la cadena vacía » es el indicativo que tiene Python para detectar que ha llegado al final del archivo, hecho que podremos utilizar en nuestro código a la hora de hacer lecturas.

Otro método que debes conocer es readline() que, a diferencia del anterior, que realiza una lectura completa, recupera cada línea de una en una:

>>> fichero.seek(0)
0
>>> fichero.readline()
'Comienza el fichero con una mención a la casa de la pradera.\n'

Como el cursor estará posicionado al comienzo de la línea siguiente, cada nueva ejecución de readline() nos recuperará la línea adecuada:

>>> fichero.readline()
'La segunda línea suele hallarse después de la primera.\n'
>>> fichero.readline()
'\n'
>>> fichero.readline()
'Esta es la cuarta línea, en la tercera había una línea en blanco.\n'
>>> fichero.readline()
'Es una verdadera lástima que esta sea la última línea.\n'
>>> fichero.readline()
''

Observa nuevamente la cadena vacía para indicar que ya hemos alcanzado el final del archivo.

A continuación, uno de mis metodos favoritos: readlines(), como el anterior, pero esta vez en plural.

Este método devuelve una lista en la que cada elemento es una línea del fichero:

>>> fichero.seek(0)
0
>>> fichero.readlines()
['Comienza el fichero con una mención a la casa de la pradera.\n', 
'La segunda línea suele hallarse después de la primera.\n', 
'\n', 
'Esta es la cuarta línea, en la tercera había una línea en blanco.\n', 
'Es una verdadera lástima que esta sea la última línea.\n']

Asocia su salida a una variable y en una única lectura tendrás una lista que podrás manipular tranquilamente a tus anchas sin preocuparte de cursores.

Para finalizar, una vez hemos terminado de usar el objeto fichero, debemos proceder a cerrarlo, liberando así la memoria que estaba consumiendo y rompiendo el vínculo con el fichero real.

>>> fichero.close()

A partir de ahí, nuestra abstracción fichero dejará de estar disponible. Si necesitaras volver a hacer uso del archivo deberías abrirlo nuevamente.

Suficiente por hoy. No olvides las tres erres: read, readline y readlines.

Javier Montero Gabarró


Python: Aprendiendo a leer


El texto de este artículo se encuentra sometido a una licencia Creative Commons del tipo CC-BY-NC-ND (reconocimiento, no comercial, sin obra derivada, 3.0 unported)


El Club del Autodidacta


Consulta el índice completo de artículos relacionados con Python.

Python: Hace falta valor

Objetivo: entender cómo responde Python ante la modificación in situ de un objeto.

Hace unos días te presenté un fenómeno cuya comprensión era esencial para entender el modelo de memoria de Python basado en referencias. Quiero mostrarte hoy otro directamente relacionado con él.

Voy a proponerte un problema que te ayudará a testear tu conocimiento sobre Python…

Partamos de alguna operación que modifique in situ el valor de un objeto. Sin ir más lejos, tomemos, por ejemplo, el recientemente aprendido método reverse() para invertir una lista:

>>> a = [1, 2, 3]
>>> b = a.reverse()

Mi pregunta es la siguiente: ¿qué valor crees que tiene la variable b?

Recuerda que el método reverse() invierte la lista in situ (para hacerlo creando un objeto diferente recurríamos al slicing).

¿Crees que b tendrá por valor [3, 2, 1]? Se realiza la inversión y acto seguido b toma ese valor, de modo que a b le corresponde un valor de [3, 2, 1] también, como a.

O, por el contrario, ¿valdrá b, a pesar de todo [1, 2, 3]?

¿Qué piensas?

¿Sabes ya la respuesta sin comprobarla en el intérprete interactivo?

¿Por qué crees que sucede así?

¿Pondrías tu mano en el fuego?

Lamento decirte que, tanto si has elegido la primera opción como si has optado por la segunda te has equivocado completamente.

Veamos la respuesta al problema mostrando el valor de ambas variables tras la operación:

>>> a = [1, 2, 3]
>>> b = a.reverse()
>>> 
>>> a
[3, 2, 1]
>>> b
>>> 

Sorpresa: la variable b no tiene ningún valor, lo que equivale a decir que es None.

>>> type(b)
<class 'NoneType'>

Este fenómemo lo has tenido siempre delante de tus narices, aunque con mucha probabilidad te haya pasado desapercibido.

Por ejemplo, observa cómo responde el intérprete interactivo después de cualquier operación que implique la creación de un nuevo objeto:

>>> 2+3
5
>>> 'pradera'[0:3]
'pra'
>>> [1, 2, 3][::-1]
[3, 2, 1]
>>> 

Es decir, devuelve el resultado de esa operación. Si hubiésemos asignado una variable a esa operación, su valor sería precisamente ese.

Pero presta mucho atención qué sucede ante operaciones in situ, que actúan sobre el propio objeto:

>>> [1, 2, 3].append(4)
>>> [1, 2, 4].reverse()
>>> 

¡Python no devuelve absolutamente nada! O, lo que es lo mismo, devuelve el valor None.

No se trata de ningún bug de Python, sino una consideración de diseño refinadísima.

Python está diseñado expresamente así, de modo que, explícitamente, cada vez que una operación de cualquier tipo modifique in situ un objeto, no se devolverá ningún valor.

Por eso la variable b, en nuestro problema, no toma ningún valor. La inversión de la lista, desde luego, ha hecho su efecto en a, pero no hay valor devuelto por esta inversión.

Hace falta valor para tomar una decisión así, pero es algo absolutamente coherente con el modelo de memoria de Python. De no hacerlo, el sistema entero cojearía en operaciones encadenadas que combinasen modificaciones in situ con creaciones de nuevos objetos: sólo podemos encadenar operaciones (por ejemplo, ejecutando un método que actúe sobre el resultado de otro) cuando esas operaciones impliquen la creación de nuevos objetos. Si en cualquiera de ellas hay una modificación in situ no habrá valor devuelto.

En nuestro pequeño problema, la forma correcta de proceder sería esta:

>>> a = [1, 2, 3]
>>> a.reverse()
>>> b = a
>>> a
[3, 2, 1]
>>> b
[3, 2, 1]

Es decir, invertimos la lista a y sólo después realizamos la asignación de b, una vez a ha sufrido su mutación in situ.

Un pequeño precio a pagar que asegura coherencia y claridad en el código.

Javier Montero Gabarró


http://elclubdelautodidacta.es/wp/2012/10/python-hace-falta-valor/


El texto de este artículo se encuentra sometido a una licencia Creative Commons del tipo CC-BY-NC-ND (reconocimiento, no comercial, sin obra derivada, 3.0 unported)


El Club del Autodidacta


Consulta el índice completo de artículos relacionados con Python.

Problemas en las suscripciones por correo electrónico

Parece que al fin se han solucionado los problemas del plugin que se ocupa de la gestión de las suscripciones al blog a través del correo electrónico, que ha ocasionado que, durante una semana, se dejasen de recibir los mensajes con los nuevos artículos publicados.

He instalado una nueva versión de Jetpack que presumiblemente corrige el problema. Si recibes un correo con este texto será una buena señal…

Javier Montero

PD: Aprovecho para recordarte que los artículos de programación no se formatean adecuadamente en los mensajes del correo, por lo que te recomiendo que los leas directamente en el blog, en el que utilizo técnicas especiales para preservar el aspecto del código fuente.

Python: El mundo al revés

Objetivo: aprender a invertir secuencias en Python.

¿Cansado de que tu nombre figure siempre en las últimas páginas de las listas de resultados de exámenes? ¿No has podido renovar el DNI después de varias horas esperando en una cola? Si es así, necesitas leer este artículo cuanto antes.

Voy a mostrarte cómo invertir secuencias en Python, ponerlas patas arriba y presentarlas al revés.

Comencemos considerando una cadena de caracteres cualquiera:

>>> a = 'pradera'

La técnica para invertir secuencias se basa en los slices, que ya deben resultarte familiares si has leído los artículos anteriores.

Repasemos su sintaxis:

secuencia[i:j:k]

El primer parámetro indica el índice de comienzo del trozo y el segundo el final, pero sin incluir. El tercero es opcional y, cuando está presente, indica el incremento con el que recorreremos el camino entre el principio y el fin.

Veamos algunos ejemplos:

>>> a[0:3]
'pra'

Hemos cortado un fragmento que abarca desde el carácter que tiene por índice 0 (es decir, el primero), hasta el que tiene 3 sin incluir (esto es, hasta el índice 2).

El siguiente slice hace uso de los tres parámetros:

>>> a[1:6:2]
'rdr'

Para comprenderlo, extrae primero el fragmento que correspondería a [1:6]:

'rader'

Y ahora recorre la secuencia de dos en dos, empezando por el primero:

'rdr'

El siguiente ejemplo muestra la omisión del primer parámetro, indicando que comenzamos desde el principio:

>>> a[:4]
'prad'

O del segundo, lo que significa que sigue hasta el final:

>>> a[3:]
'dera'

O de ambos:

>>> a[:]
'pradera'

Recuerda que ya presentamos esta última técnica como método para duplicar una secuencia.

Visto este pequeño repaso, lo que nos interesa muy particularmente es el caso en el que el tercer parámetro del slice es negativo. Eso significa que el fragmento se extrae no de izquierda a derecha, sino al revés, de derecha a izquierda.

Observa el ejemplo:

>>> a[5:1:-1]
'reda'

Analicemos esto con cuidado esto para asegurarnos de que lo entendemos bien:

Lo primero que quizás te llame la atención es que el primer parámetro es mayor que el segundo. Esto es así debido a que estamos recorriendo la secuencia de derecha a izquierda. El índice de comienzo siempre será más alto (o al menos igual) que el índice de destino.

Comenzamos el corte hacia atrás desde el carácter que tiene por índice 5: ‘r’.

¿Y dónde terminamos? En el inmediatamente anterior al indicado en el segundo parámetro. Puesto que estamos recorriendo la secuencia al revés, el anterior del índice 1 no es el índice cero sino 2: ‘a’.

Y ahora sí, tomamos de derecha a izquierda todos esos caracteres, desde un extremo hasta el otro:

'reda'

Ya estás en condiciones de entender lo que hace esto:

>>> a[::-1]
'aredarp'

Es nuestro buscado string invertido.

Como no fijamos valores iniciales ni finales estamos indicando que actuaremos sobre la cadena completa.

Apréndete bien esta técnica, es el procedimiento básico para invertir secuencias, algo que tendrás que realizar con frecuencia en tu vida como programador.

Naturalmente, con las listas (un tipo de secuencias) otro tanto de lo mismo:

>>> a = [1, 2, 3]
>>> a[::-1]
[3, 2, 1]

Es muy importante que tengas siempre presente que el slicing siempre genera un objeto nuevo. Con los strings puede parecer obvio, ya que son inmutables, pero quizás no tanto con las listas, que no lo son (pueden modificarse in-situ).

Constata que la lista sigue siendo la misma:

>>> a
[1, 2, 3]

Por último, voy a enseñarte otra técnica muy útil para invertir listas, pero con la particularidad de que realizaremos una operación destructiva, modificando in-situ la lista (aprovechándonos de su mutabilidad): el método reverse().

>>> a.reverse()
>>> a
[3, 2, 1]

Observa que no ha habido creación de un duplicado, sino que el objeto original ha sido directamente modificado.

La siguiente lista muestra el resultado de una carrera entre varios colegas:

>>> clasificacion = ['Jesús', 'Pedro', 'José Luis', 'Javier']

No es que me importe particularmente quedarme el último pero, si dispongo de recursos, ¿por qué no los habría de utilizar?

>>> clasificacion.reverse()
>>> clasificacion
['Javier', 'José Luis', 'Pedro', 'Jesús']

Ni slicing ni gaitas: he preferido actuar directamente sobre el objeto, destruyendo el anterior.

Y ahora eso ya tiene otra pinta, ¿somos pythonistas o no?

Javier Montero Gabarró


Python: El mundo al revés


El texto de este artículo se encuentra sometido a una licencia Creative Commons del tipo CC-BY-NC-ND (reconocimiento, no comercial, sin obra derivada, 3.0 unported)


El Club del Autodidacta


Consulta el índice completo de artículos relacionados con Python.

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR
Aviso de cookies