Next Up Previous Hi Index

Chapter 10

Diccionarios

Los tipos compuestos que ha visto hasta ahora (cadenas, listas y tuplas) usan enteros como �ndices. Si intenta usar cualquier otro tipo como �ndice provocar� un error.

Los diccionarios son similares a otros tipos compuestos excepto en que pueden usar como �ndice cualquier tipo inmutable. A modo de ejemplo, crearemos un diccionario que traduzca palabras inglesas al espa�ol. En este diccionario, los �ndices son strings (cadenas).

Una forma de crear un diccionario es empezar con el diccionario vac�o y a�adir elementos. El diccionario vac�o se expresa como {}:

>>> ing\_a\_esp = {}
>>> ing\_a\_esp['one'] = 'uno'
>>> ing\_a\_esp['two'] = 'dos'

La primera asignaci�n crea un diccionario llamado ing_a_esp; las otras asignaciones a�aden nuevos elementos al diccionario. Podemos presentar el valor actual del diccionario del modo habitual:

>>> print ing\_a\_esp
{'one': 'uno', 'two': 'dos'}

Los elementos de un diccionario aparecen en una lista separada por comas. Cada entrada contiene un �ndice y un valor separado por dos puntos (:). En un diccionario, los �ndices se llaman claves, por eso los elementos se llaman pares clave-valor.

Otra forma de crear un diccionario es dando una lista de pares clave-valor con la misma sintaxis que la salida del ejemplo anterior:

>>> ing\_a\_esp = {'one': 'uno', 'two': 'dos', 'three': 'tres'}

Si volvemos a imprimir el valor de ing_a_esp, nos llevamos una sorpresa:

>>> print ing\_a\_esp
{'one': 'uno', 'three': 'tres', 'two': 'dos'}

�Los pares clave-valor no est�n en orden! Afortunadamente, no necesitamos preocuparnos por el orden, ya que los elementos de un diccionario nunca se indexan con �ndices enteros. En lugar de eso, usamos las claves para buscar los valores correspondientes:

>>> print ing\_a\_esp['two']
'dos'

La clave 'two' nos da el valor 'dos' aunque aparezca en el tercer par clave-valor.

10.1 Operaciones sobre diccionarios

La sentencia del elimina un par clave-valor de un diccionario. Por ejemplo, el diccionario siguiente contiene los nombres de varias frutas y el n�mero de esas frutas en el almac�n:

>>> inventario = {'manzanas': 430, 'bananas': 312,
...               'naranjas': 525, 'peras': 217}
>>> print inventario
{'naranjas': 525, 'manzanas': 430, 'peras': 217, 'bananas': 312}

Si alguien compra todas las peras, podemos eliminar la entrada del diccionario:

>>> del inventario['peras']
>>> print inventario
{'naranjas': 525, 'manzanas': 430, 'bananas': 312}

O si esperamos recibir m�s peras pronto, podemos simplemente cambiar el inventario asociado con las peras:

>>> inventario['peras'] = 0
>>> print inventario
{'naranajas': 525, 'manzanas': 430, 'peras': 0, 'bananas': 312}

La funci�n len tambi�n funciona con diccionarios; devuelve el n�mero de pares clave-valor:

>>> len(inventario)
4

10.2 M�todos del diccionario

Un m�todo es similar a una funci�n, acepta par�metros y devuelve un valor, pero la sintaxis es diferente. Por ejemplo, el m�todo keys acepta un diccionario y devuelve una lista con las claves que aparecen, pero en lugar de la sintaxis de la funci�n keys(ing_a_esp), usamos la sintaxis del m�todo ing_a_esp.keys().

>>> ing\_a\_esp.keys()
['one', 'three', 'two']

Esta forma de notaci�n de punto especifica el nombre de la funci�n, keys, y el nombre del objeto al que se va a aplicar la funci�n, ing_a_esp. Los par�ntesis indican que este m�todo no admite par�metros.

La llamda a un m�todo se denomina invocaci�n; en este caso, dir�amos que estamos invocando keys sobre el objeto ing_a_esp.

El m�todo values es similar; devuelve una lista de los valores del diccionario:

>>> ing\_a\_esp.values()
['uno', 'tres', 'dos']

El m�todo items devuelve ambos, una lista de tuplas con los pares clave-valor del diccionario:

>>> ing\_a\_esp.items()
[('one','uno'), ('three', 'tres'), ('two', 'dos')]

La sintaxis nos proporciona informaci�n muy �til acerca del tipo de datos. Los corchetes indican que es una lista. Los par�ntesis indican que los elementos de la lista son tuplas.

Si un m�todo acepta un argumento, usa la misma sintaxis que una llamada a una funci�n. Por ejemplo, el m�todo has_key acepta una clave y devuelve verdadero (1) si la clave aparece en el diccionario:

>>> ing\_a\_esp.has_key('one')
1
>>> ing\_a\_esp.has_key('deux')
0

Si usted invoca un m�todo sin especificar un objeto, provoca un error. En este caso, el mensaje de error no es de mucha ayuda:

>>> has_key('one')
NameError: has_key

10.3 Asignaci�n de alias y copiado

Debe usted estar atento a los alias a causa de la mutabilidad de los diccionarios. Si dos variables se refieren al mismo objeto los cambios en una afectan a la otra.

Si quiere modificar un diccionario y mantener una copia del original, use el m�todo copy. Por ejemplo, opuestos es un diccionario que contiene pares de opuestos:

>>> opuestos = {'arriba': 'abajo', 'derecho': 'torcido',
...             'verdadero': 'falso'}
>>> alias = opuestos
>>> copia = opuestos.copy()

alias y opuestos se refieren al mismo objeto; copia hace referencia a una copia nueva del mismo diccionario. Si modificamos alias, opuestos tambi�n resulta cambiado:

>>> alias['derecho'] = 'sentado'
>>> opuestos['derecho']
'sentado'

Si modificamos copia, opuestos no var�a:

>>> copia['derecho'] = 'privilegio'
>>> opuestos['derecho']
'sentado'

10.4 Matrices dispersas

En la Secci�n usamos una lista de listas para representar una matriz. Es una buena opci�n para una matriz en la que la mayor�a de los valores es diferente de cero, pero piense en una matriz como �sta:

La representaci�n de la lista contiene un mont�n de ceros:

matriz = [ [0,0,0,1,0],
           [0,0,0,0,0],
           [0,2,0,0,0],
           [0,0,0,0,0],
           [0,0,0,3,0] ]

Una posible alternativa es usar un diccionario. Como claves, podemos usar tuplas que contengan los n�meros de fila y columna. �sta es la representaci�n de la misma matriz por medio de un diccionario:

matriz = {(0,3): 1, (2, 1): 2, (4, 3): 3}

S�lo hay tres pares clave-valor, una para cada elemento de la matriz diferente de cero. Cada clave es una tupla, y cada valor es un entero.

Para acceder a un elemento de la matriz, podemos usar el operador []:

matriz[0,3]
1

F�jese en que la sintaxis para la representaci�n por medio del diccionario no es la misma de la representaci�n por medio de la lista anidada. En lugar de dos �ndices enteros, usamos un �ndice que es una tupla de enteros.

Hay un porblema. Si apuntamos a un elemento que es cero, se produce un error porque en el diccionario no hay una entrada con esa clave:

>>> matriz[1,3]
KeyError: (1, 3)

El m�todo get soluciona este problema:

>>> matriz.get((0,3), 0)
1

El primer argumento es la clave; el segundo argumento es el valor que debe devolver get en caso de que la clave no est� en el diccionario:

>>> matriz.get((1,3), 0)
0

get mejora sensiblemente la sem�ntica del acceso a una matriz dispersa. L�stima de sintaxis.

10.5 Pistas

Si estuvo jugando con la funci�n fibonacci de la Secci�n 5.7, es posible que haya notado que cuanto m�s grande es el argumento que le da, m�s tiempo le cuesta ejecutarse. M�s a�n, el tiempo de ejecuci�n aumenta muy r�pidamente. En nuestra m�quina, fibonacci(20) acaba instant�neamente, fibonacci(30) tarda m�s o menos un segundo, y fibonacci(40) tarda una eternidad.

Para entender por qu�, observe este gr�fico de llamadas de fibonacci con n=4:

Un gr�fico de llamadas muestra un conjunto de cajas de funci�n con l�neas que conectan cada caja con las cajas de las funciones a las que llama. En lo alto del gr�fico, fibonacci con n=4 llama a fibonacci con n=3 y n=2. A su vez, fibonacci con n=3 llama a fibonacci con n=2 y n=1. Y as� sucesivamente.

Cuente cu�ntas veces se llama a fibonacci(0) y fibonacci(1). Es una soluci�n ineficaz al problema, y empeora mucho tal como crece el argumento.

Una buena soluci�n es llevar un registro de los valores que ya se han calculado almacen�ndolos en un diccionario. A un valor que ya ha sido calculado y almacenado para un uso posterior se le llama pista. Aqu� hay una implementaci�n de fibonacci con pistas:

anteriores = {0:1, 1:1}

def fibonacci(n):
  if anteriores.has_key(n):
    return anteriores[n]
  else:
    nuevoValor = fibonacci(n-1) + fibonacci(n-2)
    anteriores[n] = nuevoValor
    return nuevoValor

El diccionario llamado anteriores mantiene un registro de los valores de Fibonacci que ya conocemos. El programa comienza con s�lo dos pares: 0 corresponde a 1 y 1 corresponde a 1.

Siempre que se llama a fibonacci comprueba si el diccionario contiene el resultado ya calculado. Si est� ah�, la funci�n puede devolver el valor inmediatamente sin hacer m�s llamadas recursivas. Si no, tiene que calcular el nuevo valor. El nuevo valor se a�ade al diccionario antes de que la funci�n vuelva.

Con esta versi�n de fibonacci, nuestra m�quina puede calcular fibonacci(40) en un abrir y cerrar de ojos. Pero cuando intentamos calcular fibonacci(50), nos encontramos con otro problema:

>>> fibonacci(50)
OverflowError: integer addition

La respuesta, como ver� en un momento, es 20.365.011.074. El problema es que este n�mero es demasiado grande para caber en un entero de Python. Se desborda. Afortunadamente, hay una soluci�n f�cil para este problema.

10.6 Enteros largos

Python proporciona un tipo llamado long int que puede manejar enteros de cualquier tama�o. Hay dos formas de crear un valor long int. Una es escribir un entero con una L may�scula al final:

>>> type(1L)
<type 'long int'>

La otra es usar la funci�n long para convertir un valor en long
int
. long acepta cualquier tipo num�rico e incluso cadenas de d�gitos:

>>> long(1)
1L
>>> long(3.9)
3L
>>> long('57')
57L

Todas las operaciones matem�ticas funcionan sobre los long ints, as� que no tenemos que hacer mucho para adaptar fibonacci:

>>> previous = {0:1L, 1:1L}
>>> fibonacci(50)
20365011074L

Simplemente cambiando el contenido inicial de anteriores cambiamos el comportamiento de fibonacci. Los primeros dos n�meros de la secuencia son long ints, as� que todos los n�meros subsiguientes lo ser�n tambi�n.

Como ejercicio, modifique factorial de forma que produzca un long int como resultado.

10.7 Contar letras

En el cap�tulo 7 escribimos una funci�n que contaba el n�mero de apariciones de una letra en una cadena. Una versi�n m�s gen�rica de este problema es crear un histograma de las letras de la cadena, o sea, cu�ntas veces aparece cada letra.

Ese histograma podr�a ser �til para comprimir un archivo de texto. Como las diferentes letras aparecen con frecuencias distintas, podemos comprimir un archivo usando c�digos cortos para las letras m�s habituales y c�digos m�s largos para las que aparecen con menor frecuencia.

Los diccionarios facilitan una forma elegante de generar un histograma:

>>> cuentaLetras = {}
>>> for letra in "Mississippi":
...   cuentaLetras[letra] = cuentaLetras.get (letra, 0) + 1
...
>>> cuentaLetras
{'M': 1, 's': 4, 'p': 2, 'i': 4}
>>>

Inicialmente, tenemos un diccionario vac�o. Para cada letra de la cadena, buscamos el recuento actual (posiblemente cero) y lo incrementamos. Al final, el diccionario contiene pares de letras y sus frecuencias.

Puede ser m�s atractivo mostrar el histograma en orden alfab�tico. Podemos hacerlo con los m�todos items y sort:

>>> itemsLetras = cuentaLetras.items()
>>> itemsLetras.sort()
>>> print itemsLetras
[('M', 1), ('i', 4), ('p', 2), ('s', 4)]

Ya hab�a visto usted el m�todo items, pero sort es el primer m�todo aplicable a listas que hemos visto. Hay varios m�s, como append, extend, y reverse. Consulte la documentaci�n de Python para ver los detalles.

10.8 Glosario

diccionario
Una colecci�n de pares clave-valor que establece una correspondencia entre claves y valores. Las claves pueden ser de cualquier tipo inmutable, los valores pueden ser de cualquier tipo.
clave
Un valor que se usa para buscar una entrada en un diccionario.
par clave-valor
Uno de los elementos de un diccionario, tambi�n llamado "asociaci�n".
m�todo
Un tipo de funci�n al que se llama con una sintaxis diferente y al que se invoca "sobre" un objeto.
invocar
Llamar a un m�todo.
pista
Almacenamiento temporal de un valor precalculado para evitar c�lculos redundantes.
desbordamiento
Un resultado num�rico que es demasiado grande para representarse en formato num�rico.


Next Up Previous Hi Index

" + str + "

Close window

Hosted by www.Geocities.ws

"); } //-->
Hosted by www.Geocities.ws

1