web-dev-qa-db-fra.com

Un dictionnaire Python est-il un exemple de table de hachage?

L'une des structures de données de base de Python est le dictionnaire, qui permet d'enregistrer des "clés" pour rechercher des "valeurs" de n'importe quel type. Est-ce implémenté de manière interne en tant que table de hachage? Sinon , qu'Est-ce que c'est?

161
Tommy Herbert

Oui, c'est un mappage de hachage ou une table de hachage. Vous pouvez lire une description de l'implémentation dict de python, écrite par Tim Peters, here .

C'est pourquoi vous ne pouvez pas utiliser quelque chose de 'non hashable' comme 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 en savoir plus sur les tables de hachage ou vérifiez comment cela a été implémenté en python et pourquoi il est implémenté de cette façon .

209
nosklo

Il doit y avoir plus dans un Python qu'une recherche de table sur hash (). Par expérimentation brutale, j'ai trouvé ceci collision de hachage:

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

Pourtant, cela ne casse pas le dictionnaire:

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

Verification sanitaire:

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

Il existe peut-être un autre niveau de recherche au-delà de hash () qui évite les collisions entre les clés du dictionnaire. Ou peut-être que dict () utilise un hash différent.

(Au fait, ceci dans Python 2.7.10. Même histoire dans Python 3.4.3 et 3.5.0 avec une collision à hash(1.1) == hash(214748749.8).)

24
Bob Stein

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

20
Ben Hoffstein

Pour développer 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']
6
Jeremy Cantrell