2010-12-03 15 views
17

Alguien tiene algunos ejemplos ordenadas de diccionarios con algunas claves interesantes (además de la secuencia canónica o entero), y cómo se utiliza esto en su programa?Teclas del diccionario Python además de cadenas y números enteros?

entiendo todo lo que necesitamos para una clave es algo hashable, lo que significa que debe ser inmutable y comparables (tiene un método __eq__() o __cmp__()).

Una cuestión relacionada es: ¿cómo puedo definir de forma rápida y hábilmente un nuevo hashable?

+2

'hashable' == puedes llamarlo método' __hash__' y obtener un int. Nada mas. Las funciones de comparación serían necesarias si los dicts/sets/etc. fuesen v.g. árboles binarios. – delnan

+0

Me parece que esta definición me ha engañado: http://docs.python.org/glossary.html#term-hashable – Pete

+1

@delnan: hashable en el contexto de Python también significa comparable; mira el enlace publicado por Pete. Pero no incluye inmutable. –

Respuesta

22

Vamos a ir por algo un poco más esotérica. Supongamos que quiere ejecutar una lista de funciones y almacenar el resultado de cada una. Para cada función que generó una excepción, desea registrar la excepción y también desea contar cuántas veces se genera cada tipo de excepción. Funciones y excepciones pueden ser utilizados como dict llaves, así que esto es fácil:

funclist = [foo, bar, baz, quux] 

results = {} 
badfuncs = {} 
errorcount = {} 

for f in funclist: 
    try: 
     results[f] = f() 
    except Exception as e: 
     badfuncs[f] = e 
     errorcount[type(e)] = errorcount[type(e)] + 1 if type(e) in errorcount else 1 

Ahora usted puede hacer if foo in badfuncs para probar si esa función produce una excepción (o if foo in results para ver si se ejecuta correctamente), if ValueError in errorcount para ver si cualquier función planteada ValueError, y así sucesivamente.

+0

Un gran ejemplo que parece una excelente manera de organizar los resultados del análisis en la memoria. corrige error error tipográfico [t] -> errorcount [f]. El recuento no parece funcionar, no estoy seguro de por qué no debería hacerlo cuando repito las funciones nuevamente sin reiniciar el dict. – Pete

+0

En realidad, se suponía que era 'tipo (e)' en lugar de 't' ya que este diccionario debe contar el número de veces que se generó cada tipo de excepción. Inicialmente tenía una línea allí que decía 't = tipo (e)' que es de donde vino la 't'. De todos modos, arreglado. :-) – kindall

6

Se puede utilizar una tupla como una clave, por ejemplo, si desea crear un índice de varias columnas. Aquí hay un ejemplo simple:

>>> index = {("John", "Smith", "1972/01/01"): 123, ("Bob", "Smith", "1972/01/02"): 124} 
>>> index 
{('Bob', 'Smith', '1972/01/02'): 124, ('John', 'Smith', '1972/01/01'): 123} 
>>> index.keys() 
[('Bob', 'Smith', '1972/01/02'), ('John', 'Smith', '1972/01/01')] 
>>> index['John', 'Smith', '1972/01/01'] 
123 

Para un ejemplo de cómo usar un diccionario como una clave (un diccionario hashable) ver esta respuesta: Python hashable dicts

+1

Tenga en cuenta que puede omitir la tupla parens, teniendo así una gran mejora en la legibilidad del código ('index ['John', 'Smith', '1972/01/01']') –

+0

gracias! Actualicé la respuesta para reflejar su sugerencia. – patrickmdnet

2

Tenga en cuenta que en realidad nunca he utilizado este, pero Siempre he pensado usar tuplas, ya que las teclas podrían dejarte hacer algunas cosas interesantes. Me parece una forma conveniente de asignar coordenadas de cuadrícula, por ejemplo. Usted puede pensar en esto como una cuadrícula en un juego de video (tal vez algún tipo de tácticas de juego como Fire Emblem):

>>> Terrain = { (1,3):"Forest", (1,5):"Water", (3,4):"Land" } 
>>> print Terrain 
{(1, 5): 'Water', (1, 3): 'Forest', (3, 4): 'Land'} 
>>> print Terrain[(1,3)] 
Forest 
>>> print Terrain[(1,5)] 
Water 
>>> x = 3 
>>> y = 4 
>>> print Terrain[(x,y)] 
Land 

Algo por el estilo.

Editar: Como Mark Rushakof señaló en los comentarios, estoy básicamente la intención de que esto sea un sparse array.

+0

Sí, las tuplas como claves son geniales. Los he usado para almacenar resultados de datos ordenados en contenedores. – dtlussier

+0

Creo que todo el mundo en su sano juicio usaría una matriz bidimensional para almacenar los tipos de terreno del mapa :) –

+1

@Sven Marnach: En realidad me gustan las tuplas, ya que es un poco más sencillo omitir espacios (es decir, déjalos en blanco). – eldarerathis

6

Olvidó el método probablemente más importante para que un objeto sea hashable: __hash__().

La aplicación más corto de su propio tipo hashable es la siguiente:

class A(object): 
    pass 

Ahora se puede utilizar instancias de A claves como diccionario:

d = {} 
a = A() 
b = A() 
d[a] = 7 
d[b] = 8 

Esto se debe a que las clases definidas por el usuario son hashable por por defecto, y su valor hash es su id, por lo que solo se compararán si son el mismo objeto.

Tenga en cuenta que los casos de A son de ninguna manera inmutable, y que se puede utilizar como diccionario sin embargo llaves. La afirmación de que las claves del diccionario deben ser inmutables solo se cumple para los tipos incorporados.

+0

Ser mutable y lavable al mismo tiempo * está permitido *, pero por lo general es una locura. – delnan

+4

Muchos tipos de objetos de Python son técnicamente mutables, pero aún son hashable. Si fuera "loco", ¿por qué los objetos creados por el usuario serían así por defecto? – kindall

+2

@kindall: No entiendo muy bien por qué 'object .__ hash__' se comporta de esta manera (ya que los objetos que lo usan no funcionan como se esperaban como claves del diccionario). Pero vea http://wiki.python.org/moin/DictionaryKeys para saber por qué es un gran dolor de cabeza. – delnan

1

que no tienen idea de por qué te gustaría hacerlo (y preferiblemente, por favor no hacerlo) ...pero junto a cadenas y enteros, también puedes usar ambos simultáneamente. Es decir, como un principiante, lo encontré a la vez potente y sorprendente que:

foo = { 1:'this', 2:'that', 'more':'other', 'less':'etc' } 

es un diccionario de plena actualidad, que proporciona acceso a foo[2] tan fácilmente como lo hace a foo['more'].

Cuestiones relacionadas