web-dev-qa-db-fra.com

Liste insaisissable, mais Tuple peut-il être lavé?

Dans Comment hacher des listes? On m'a dit que je devrais d'abord me convertir en tuple, par exemple. [1,2,3,4,5] à (1,2,3,4,5).

Ainsi, le premier ne peut pas être haché, mais le second le peut. Pourquoi*?


*Je ne cherche pas vraiment une explication technique détaillée, mais plutôt une intuition

20
gsamaras

Principalement, parce que les tuples sont immuables. Supposons les travaux suivants:

>>> l = [1, 2, 3]
>>> t = (1, 2, 3)
>>> x = {l: 'a list', t: 'a Tuple'}

Maintenant, que se passe-t-il quand vous faites l.append(4)? Vous avez modifié la clé dans votre dictionnaire! De loin! Si vous connaissez le fonctionnement des algorithmes de hachage, cela devrait vous effrayer. Les tuples, en revanche, sont absolument immuables. t += (1,) peut sembler modifier le tuple, mais ce n'est pas le cas: il crée simplement un nouveau Tuple, en laissant la clé de votre dictionnaire inchangée.

35
val

Vous pourriez totalement faire ce travail, mais je parie que vous ne voudriez pas les effets.

from functools import reduce
from operator import xor

class List(list):
    def __hash__(self):
        return reduce(xor, self)

Voyons maintenant ce qui se passe:

>>> l = List([23,42,99])
>>> hash(l)
94
>>> d = {l: "Hello"}
>>> d[l]
'Hello'
>>> l.append(7)
>>> d
{[23, 42, 99, 7]: 'Hello'}
>>> l
[23, 42, 99, 7]
>>> d[l]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: [23, 42, 99, 7]

edit: Alors j'y ai réfléchi un peu plus. Vous pouvez faire fonctionner l'exemple ci-dessus si vous retournez l'id de la liste sous forme de valeur de hachage:

class List(list):
    def __hash__(self):
        return id(self)

Dans ce cas, d[l] vous donnera 'Hello', mais ni d[[23,42,99,7]] ni d[List([23,42,99,7])] ne le seront (car vous créez un nouveau [Ll]ist.

7
L3viathan

Puisqu'une liste est modifiable, si vous la modifiez, vous modifieriez également son hachage, ce qui gâcherait le point d'avoir un hachage (comme dans un ensemble ou une clé dict).

4
polku

Parce que les listes sont modifiables et que les n-uplets ne le sont pas.

4
Daniel Roseman

Les réponses sont bonnes. La raison est la mutabilité. Si nous pouvions utiliser list in dict comme clés; (ou tout objet mutable), nous serions alors en mesure de changer la clé en modifiant cette clé (accidentellement ou intentionnellement). Cela entraînerait une modification de la valeur de hachage de la clé dans le dictionnaire, ce qui nous empêcherait de retracer la valeur de cette structure de données à l'aide de cette clé. Les valeurs de hachage et les tables de hachage permettent de mapper facilement les données volumineuses en les mappant vers des index qui stockent les entrées de valeur réelle. 

En savoir plus sur eux ici: - 

Tables de hachage & Fonctions de hachage & Tableaux associés

1
Vicrobot

Tous les Tuple ne sont pas nécessairement hashable.

x = (1,[2,3])
print(type(x))
print(hash(x))
0
user1436465