2008-09-22 16 views
126

L'une des structures de données de base en Python est le dictionnaire, qui permet d'enregistrer des "clés" pour rechercher des "valeurs" de n'importe quel type. Est-ce implémenté en interne comme une table de hachage? Si non, qu'est-ce que c'est?Un dictionnaire Python est-il un exemple de table de hachage?

+1

Voici un discours de Brandon Craig Rhodes discuter comment fonctionne le dictionnaire python , https://www.youtube.com/watch?v=C4Kc8xzcA68. – chandola

Répondre

174

Oui, il s'agit d'un mappage de hachage ou d'une table de hachage. Vous pouvez lire une description de l'implémentation dict de python, telle que rédigée par Tim Peters, here.

Voilà pourquoi vous ne pouvez pas utiliser quelque chose « non indexables » comme une clé dict, comme une liste:

>>> 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 

Vous pouvez read more about hash tables ou check how it has been implemented in python et why it is implemented that way.

+1

Le lien de Tim Peters à briser, est-il un lien propre là-bas? –

+1

@MattAlcock: J'ai mis à jour le lien. Parfois (généralement parce que quelqu'un veut que son adresse e-mail soit supprimée quelque part) les archives de la liste python sont reconstruites et les identifiants des emails changent, cassant ainsi ces liens. Les administrateurs de pydotorg essaient généralement d'éviter cela ces jours-ci. –

+0

Mais utiliser '.keys()' peut récupérer une liste de clés. Une table de hachage réelle ne stocke pas les clés, mais seulement des hachages pour économiser de l'espace. –

17

Oui. En interne, il est implémenté en tant que hachage ouvert basé sur un polynôme primitif sur Z/2 (source).

29

Si vous êtes intéressé par les détails techniques, un article dans Beautiful Code traite des composants internes de l'implémentation dict de Python.

+1

C'était l'un de mes chapitres préférés dans le code Beautiful. – DGentry

5

Pour élargir l'explication 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

Il doit y avoir plus d'un dictionnaire Python d'une recherche de table sur hachage(). Par l'expérimentation brute j'ai trouvé cette collision de hachage :

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

Pourtant, il ne casse pas le dictionnaire:

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

Sanity chèque:

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

Peut-être il y a un autre niveau de recherche au-delà hash() qui évite les collisions entre les clés du dictionnaire. Ou peut-être dict() utilise un hachage différent.

(Soit dit en passant, ce en Python 2.7.10. Même chose en Python et 3.5.0 avec 3.4.3 une collision à hash(1.1) == hash(214748749.8).)

+3

Il a des solutions de contournement pour les collisions. –

+0

Il utilise '__eq__' pour résoudre les collisions. – dmitry

+2

Les collisions sont donc inévitables. Set S peut contenir un nombre infini d'éléments, et vous voulez qu'il hache un nombre qu'un ordinateur peut stocker. Chaque implémentation utilisable d'une table de hachage résout des collisions, deux des méthodes les plus fréquentes étant a) l'adressage ouvert et b) le chaînage. Juste parce qu'il n'utilise pas un hachage parfait ne signifie pas que ce n'est pas une table de hachage. – TurnipEntropy