2008-09-22 14 views
126

Una de las estructuras de datos básicos en Python es el diccionario, que permite grabar "claves" para buscar "valores" de cualquier tipo. ¿Esto se implementa internamente como una tabla hash? Si no, ¿qué es?¿Es un diccionario de Python un ejemplo de una tabla hash?

+1

Aquí es una charla de Brandon Craig Rodas discutir cómo funciona diccionario de Python , https://www.youtube.com/watch?v=C4Kc8xzcA68. – chandola

Respuesta

174

Sí, es un mapeo hash o una tabla hash. Puede leer una descripción de la implementación del dict de Python, según lo escrito por Tim Peters, here.

Es por eso que no se puede usar algo 'no hashable' como clave dict, como una lista:

>>> a = {} 
>>> b = ['some', 'list'] 
>>> hash(b) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: list objects are unhashable 
>>> a[b] = 'some' 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: list objects are unhashable 

Puede read more about hash tables o check how it has been implemented in python y why it is implemented that way.

+1

El enlace de Tim Peters parece estar roto, ¿hay un enlace limpio por ahí? –

+1

@MattAlcock: He actualizado el enlace. Algunas veces (generalmente debido a que alguien quiere que su dirección de correo electrónico sea eliminada en alguna parte), los archivos de la lista python se reconstruyen y los identificadores de correos electrónicos cambian, rompiendo así estos enlaces. Los administradores de pydotorg generalmente intentan evitar eso en estos días. –

+0

Pero el uso de '.keys()' puede recuperar una lista de claves. Una tabla hash real no almacenaría claves, solo hashes para ahorrar espacio. –

17

Sí. Internamente se implementa como hash abierto basado en un polinomio primitivo sobre Z/2 (source).

29

Si está interesado en los detalles técnicos, un artículo en Beautiful Code se ocupa de los aspectos internos de la implementación de Python dict.

+1

Ese fue uno de mis capítulos favoritos en Beautiful Code. – DGentry

5

de ampliar la explicación de nosklo:

a = {} 
b = ['some', 'list'] 
a[b] = 'some' # this won't work 
a[tuple(b)] = 'some' # this will, same as a['some', 'list'] 
11

Debe haber más de un diccionario de Python que una búsqueda en la tabla de hash de(). Por experimentación bruta encontré este hash de colisión:

>>> hash(1.1) 
2040142438 
>>> hash(4504.1) 
2040142438 

Sin embargo, no se rompe el diccionario:

>>> d = { 1.1: 'a', 4504.1: 'b' } 
>>> d[1.1] 
'a' 
>>> d[4504.1] 
'b' 

cordura cheque:

>>> for k,v in d.items(): print(hash(k)) 
2040142438 
2040142438 

Posiblemente hay otro nivel de búsqueda más allá hash() que evita las colisiones entre las teclas del diccionario. O tal vez dict() usa un hash diferente.

(Por cierto, esto en Python 2.7.10. La misma historia en Python 3.4.3 y 3.5.0 con una colisión en hash(1.1) == hash(214748749.8).)

+3

Tiene soluciones para colisiones. –

+0

Utiliza '__eq__' para resolver colisiones. – dmitry

+2

Entonces las colisiones son inevitables. El conjunto S puede contener un número infinitamente grande de elementos, y usted quiere hacer un hash con un número que una computadora puede almacenar. Cada implementación utilizable de una tabla hash resuelve colisiones, con dos de los métodos más frecuentes son a) direccionamiento abierto yb) encadenamiento. El hecho de que no utilice un hash perfecto no significa que no sea una tabla hash. – TurnipEntropy

Cuestiones relacionadas