Diccionarios

Los diccionarios no preservan el orden de los elementos: éste depende de las claves que se usen, del orden en el que se ingresan los datos y de otros factores. Además, no se puede iterar directamente sobre los elementos, aunque Python provee funciones para hacerlo (y también para iterar sobre las claves).

Para crear un diccionario, escribimos los pares clave-valor entre llaves, separando cada par por una coma:

>>> mi_diccionario = { 'nombre': 'Juan', 'apellido': 'Perez', 'pais':
 'Uruguay' }
>>> print mi_diccionario['nombre']
Juan

Un diccionario puede ser expandido simplemente asignando un valor a un nuevo índice. También podemos eliminar un valor del diccionario usando del:

>>> mi_diccionario['edad'] = 32
>>> del mi_diccionario['pais'] >>> print mi_diccionario {'edad': 32, 'nombre': 'Juan', 'apellido': 'Perez'} # notar que se agregó la clave 'edad', se eliminó la clave 'país', y no se preservó el orden

Si intentamos acceder a una clave no definida, Python lanza la excepción KeyError. Para evitarla, podemos comprobar fácilmente si la clave está en el diccionario usando el operador in:

>>> print mi_diccionario['una_clave_que_no_existe']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'una_clave_que_no_existe'
>>> if 'edad' in mi_diccionario:
...     print mi_diccionario['edad']
...
32

Otra forma de evitar el error es utilizar el método get(). Este método recibe dos parámetros: la clave cuyo valor se quiere obtener y el valor a retornar si la clave no está definida. Si no se especifica el segundo parámetro, get devuelve None:

>>> print mi_diccionario.get('edad')
32
>>> print mi_diccionario.get('una_clave_que_no_existe') None>>> print mi_diccionario.get('una_clave_que_no_existe', 'valor predeterminado') valor predeterminado

Al igual que las secuencias, los diccionarios también pueden ser recorridos con un bucle for. La diferencia es que en vez de iterar en orden sobre los elementos, el bucle for itera sobre las claves sin un orden preestablecido:

>>> for clave in mi_diccionario:
...  print clave, ": ", mi_diccionario[clave]
...
edad :  32
nombre : J
uan apellido : Perez

Usando el método items(), obtenemos una lista de tuplas (clave, valor), que podemos usar en el for:

>>> for (clave, valor) in mi_diccionario.items():
...  print clave, ": ", valor
...
edad :  32
nombre : J
uanapellido : Perez

Los diccionarios soportan otras operaciones: el método copy() devuelve una copia, y el método update() permite agregar a un diccionario las claves y valores de otro:

>>> dic = mi_diccionario.copy()
>>> print dic
{'edad': 32, 'nombre': 'Juan', 'apellido': 'Perez'}
>>> dic.update({'pais': 'Uruguay', 'idioma': 'Español' })
>>> print dic
{'edad': 32, 'nombre': 'Juan', 'idioma': 'Español', 'apellido': 'Perez', 
'pais': 'Uruguay'}

Funciones

Las funciones en Python se declaran con la palabra clave def, seguida del nombre de la función y de sus argumentos. Como todo bloque en Python, la declaración termina con dos puntos (“:”) y el código siguiente debe estar sangrado a un nivel mayor:

def mifuncion(parametro1, parametro2):
    código de la función

Una vez definida, la función puede ser llamada desde cualquier parte de nuestro archivo Python, simplemente con su nombre. Además de recibir valores por vía de sus parámetros, la función puede acceder a variables definidas fuera de ella y en el mismo archivo (módulo), usando la sentencia global.

Para devolver un valor, se utiliza la sentencia return. Este valor se puede obtener por asignación. Veamos un ejemplo:

variable_externa = 'HOLA'

def mi_funcion(param1, param2, ...):
# código de la función
global variable_externa
return variable_externa

mifuncion(....) # ejecuta el código de la función mi_variable1 = mi_funcion(var1, var2, ...) # mi_variable = 'HOLA'

Vale notar que la función puede devolver solamente un valor (objeto), sin embargo, se puede simular la devolución de valores múltiples gracias al empaquetado: valores separados por coma luego de la sentencia return se convierten a una tupla y lo que devuelve la función es esa tupla. Luego podemos recibir los valores devueltos como una tupla o desempaquetarlos:

>>> def mi_f():
...     return 'a', 'b'
...
>>> var1, var2 = mi_f()   # var1 = 'a', var2 = 'b'
>>> t_var = mi_f()        # t_var: tupla formada por 'a' y 'b'
>>> t_var
('a', 'b')

Las funciones en Python pueden además asignarse y pasarse como parámetro a otras funciones.

Manejando archivos

En Python, así como en cualquier otro lenguaje, los archivos se manipulan en tres pasos: primero se abren, luego se opera sobre ellos y por último se cierran.

Apertura

Para abrir un archivo debemos usar la función open(), que recibe como parámetros el nombre del archivo y el modo en el que se debe abrir. De forma predeterminada (es decir, si se omite el segundo parámetro), el archivo se abre como sólo lectura.
Es importante tener en cuenta que todas las operaciones están limitadas a la forma en la que se abra el archivo: no se puede leer de un archivo abierto solamente para escritura, ni escribir en un archivo abierto como solo lectura.

Modos
  • r: Sólo lectura. No se podrá escribir en el archivo.
  • w: Sólo escritura. Trunca el archivo al momento de abrirlo.
  • a: Sólo escritura. Escribe al final del archivo.

En cualquiera de los modos, si el archivo no existe, es creado. Opcionalmente se puede añadir + al modo para que se abra en modo lectura y escritura a la vez; aunque esto no suele ser necesario y requiere cuidado para que funcione correctamente.

Otro modificador posible es b, que sirve para trabajar con archivos binarios. Esto es necesario en Windows para manejar correctamente archivos de imágenes, o música (toda clase de archivos que no sean texto simple), porque el mismo SO hace diferencia entre archivos binarios y de texto. Esto no sucede en sistemas tipo UNIX (como Mac OS, o Linux), y por tanto en estos sistemas el modificador b no hace ninguna diferencia.

Lectura

Una vez abierto el archivo, podemos leer el contenido hacia una cadena con read(), leer una línea con readline(), u obtener una lista conteniendo las líneas del archivo con readlines(). Los tres métodos aceptan un parámetro entero opcional que define el número máximo de bytes a leer del archivo. Si este parámetro es negativo o simplemente se omite, read y readlines leerán todo el archivo y readline una línea completa sin importar su largo.

Otra forma de leer el archivo es leer línea por línea en un bucle for, ya que el objeto archivo es iterable.

Para ejemplificar lo mencionado hasta ahora, supongamos que tenemos un archivo prueba.txt con el siguiente contenido:

Esto es
una prueba
de lectura!

tenemos varias formas de leerlo:

>>> archivo = open('prueba.txt', 'r') # sólo lectura. Con modificadores, podría usar 'r+', 'rb', o 'rb+'
>>> print archivo.read()              # leer todo
Esto es
una prueba
de lectura!
>>> print archivo.readline()          # leer 1 línea.
Esto es
>>> print archivo.readlines()   # leer todas las líneas como una lista.

['Esto es\n', 'una prueba\n', 'de lectura!']   # nótese que siempre se 
                                                 incluyen los saltos de 
                                                 línea.
>>> print archivo.read(2)             # leer como máximo 2 bytes
Es
>>> print archivo.readline(4)         # leer 1 línea completa o 4 bytes,
                                        lo que ocurra primero.
Esto
>>> for linea in archivo: # con un bucle for. Esta es la forma recomendada de lectura por líneas.
... print linea
...
Esto es # Notar la línea vacía. Esto es porque la cadena leída incluye un salto de línea al final, y print agrega otro.

una prueba
de lectura!

Es importante notar que los ejemplos anteriores no funcionan en secuencia tal cual fueron escritos. Esto es debido a que una vez que se lee contenido del archivo, la siguiente lectura comenzará desde donde acabó la anterior. Es decir, si leemos 4 bytes de la primera línea (“Esto”), una siguiente lectura de 3 bytes devolverá ” es”. Todo archivo contiene un puntero interno que actúa como un cursor o como un punto de partida para las funciones de lectura o escritura y a su vez cada vez que se usa una de estas funciones, el puntero interno se mueve

Para manipular el puntero interno existen los métodos seek, que recibe como parámetro la posición a la que debe mover el puntero (0 para moverlo hacia el principio del archivo) y tell, que devuelve la posición actual del puntero.

Escritura

Si lo que queremos es escribir en el archivo, tenemos los métodos write y writelines. Contrapartes de read y readlines respectivamente, write escribe una cadena al archivo y writelines recibe una lista de líneas para escribir. Por ejemplo, si quisiéramos recrear el archivo prueba.txt del ejemplo anterior, podemos hacerlo de dos formas:

>>> archivo = open('prueba.txt', 'w')  # escritura y truncado
>>> archivo.write("Esto es\nuna prueba\nde lectura!")
>>> archivo.writelines(['Esto es\n', 'una prueba\n', 'de lectura!'])  

# notar la inclusión explícita de saltos de línea
>>> archivo.close()

Cierre

Cuando terminamos de trabajar con el archivo, lo cerramos con close(). Esto libera el archivo para ser usado por otros programas, y además asegura que los cambios sobre él se guarden. De más está decir que Python se encarga de cerrar todos los archivos que queden abiertos al final del programa, pero es una buena práctica no dejar nada al azar y cerrar el archivo tan pronto como se lo termina de usar.

with

A partir de Python 2.5, podemos simplificar un poco el código necesario para abrir y cerrar el archivo usando with:

with open('prueba.txt') as archivo:
    for linea in archivo:
        ....

Esto nos libera de tener que cerrar el archivo explícitamente, ya que Python se encargará de cerrarlo automáticamente al salir del bloque.