web-dev-qa-db-fra.com

Que fait le hash en python?

J'ai vu un exemple de code dans lequel la fonction hash est appliquée à Tuple. En conséquence, il renvoie un entier négatif. Je me demande à quoi sert cette fonction. Google n'aide pas. J'ai trouvé une page qui explique comment le hachage est calculé mais qui n'explique pas pourquoi nous avons besoin de cette fonction.

61
Roman

n hachage est un entier de taille fixe qui identifie une valeur particulière . Chaque valeur doit avoir son propre hachage. Ainsi, pour la même valeur, vous obtiendrez le même hachage, même s'il ne s'agit pas du même objet.

>>> hash("Look at me!")
4343814758193556824
>>> f = "Look at me!"
>>> hash(f)
4343814758193556824

Les valeurs de hachage doivent être créées de manière à ce que les valeurs résultantes soient uniformément réparties afin de réduire le nombre de collisions de hachage que vous obtenez. Les collisions de hachage surviennent lorsque deux valeurs différentes ont le même hachage. Par conséquent, des modifications relativement mineures entraînent souvent des hachages très différents.

>>> hash("Look at me!!")
6941904779894686356

Ces chiffres sont très utiles car ils permettent une recherche rapide des valeurs dans une vaste collection de valeurs. Deux exemples d'utilisation sont set et dict de Python. Dans un list, si vous voulez vérifier si une valeur est dans la liste, avec if x in values:, Python doit parcourir toute la liste et comparer x à chaque valeur de la liste values. Cette opération peut durer très longtemps. list. Dans un set, Python garde une trace de chaque hachage et lorsque vous tapez if x in values:, Python va obtenir la valeur de hachage pour x, le rechercher dans une structure interne et ensuite ne comparer que x avec les valeurs qui ont le même hash que x.

La même méthodologie est utilisée pour la recherche dans le dictionnaire. Cela rend la recherche dans set et dict très rapide, tandis que la recherche dans list est lente. Cela signifie également que vous pouvez avoir des objets non-hashable dans un list, mais pas dans un set ou comme clés dans un dict. L'exemple typique d'objets non-hashable est tout objet mutable, ce qui signifie que vous pouvez changer sa valeur. Si vous avez un objet mutable, il ne devrait pas être utilisable, car son hachage changerait au cours de sa vie, ce qui causerait beaucoup de confusion, puisqu'un objet pourrait se retrouver sous la mauvaise valeur de hachage dans un dictionnaire.

Notez que le hachage d'une valeur ne doit être identique que pour une exécution de Python. Dans Python 3.3, ils changeront en fait pour chaque nouvelle exécution de Python:

$ /opt/python33/bin/python3
Python 3.3.2 (default, Jun 17 2013, 17:49:21) 
[GCC 4.6.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> hash("foo")
1849024199686380661
>>> 
$ /opt/python33/bin/python3
Python 3.3.2 (default, Jun 17 2013, 17:49:21) 
[GCC 4.6.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> hash("foo")
-7416743951976404299

Ceci est plus difficile à deviner quelle valeur de hachage aura une certaine chaîne, ce qui est une fonctionnalité de sécurité importante pour les applications Web, etc.

Les valeurs de hachage ne doivent donc pas être stockées de manière permanente. Si vous devez utiliser des valeurs de hachage de manière permanente, vous pouvez jeter un coup d'œil aux types de "hachage" plus "sérieux", fonctions de hachage cryptographique , qui peuvent être utilisés pour créer des sommes de contrôle vérifiables de fichiers, etc.

108
Lennart Regebro

TL; DR:

Veuillez vous référer à le glossaire : hash() est utilisé comme raccourci pour comparer des objets. Un objet est considéré comme pouvant être remplacé s'il peut être comparé à d'autres objets. c'est pourquoi nous utilisons hash(). Il est également utilisé pour accéder aux éléments dict et set qui sont implémentés comme tables de hachage redimensionnables dans CPython .

Considérations techniques

  • habituellement, comparer des objets (ce qui peut impliquer plusieurs niveaux de récursion) coûte cher.
  • de préférence, la fonction hash() est un ordre de grandeur (ou plusieurs) moins coûteux.
  • comparer deux hachages est plus facile que comparer deux objets, c’est là que se trouve le raccourci.

Si vous lisez à propos de comment les dictionnaires sont implémentés , ils utilisent des tables de hachage, ce qui signifie que dériver une clé d'un objet est une pierre angulaire pour récupérer des objets dans des dictionnaires dans O(1). Cela dépend cependant beaucoup de votre fonction de hachage pour être résistant aux collisions . Le pire des cas pour obtenir un élément dans un dictionnaire est en fait O(n).

Sur cette note, les objets mutables ne sont généralement pas hashable. La propriété hashable signifie que vous pouvez utiliser un objet comme clé. Si la valeur de hachage est utilisée comme clé et que le contenu de ce même objet change, que doit alors renvoyer la fonction de hachage? Est-ce la même clé ou une autre? Cela dépend de la façon dont vous définissez votre fonction de hachage.

Apprendre par l'exemple:

Imaginons que nous ayons ce cours:

>>> class Person(object):
...     def __init__(self, name, ssn, address):
...         self.name = name
...         self.ssn = ssn
...         self.address = address
...     def __hash__(self):
...         return hash(self.ssn)
...     def __eq__(self, other):
...         return self.ssn == other.ssn
... 

Veuillez noter: tout ceci est basé sur l'hypothèse que le SSN ne change jamais pour un individu (je ne sais même pas où vérifier réellement ce fait à partir d'une source faisant autorité).

Et nous avons Bob:

>>> bob = Person('bob', '1111-222-333', None)

Bob va voir un juge pour changer de nom:

>>> jim = Person('jim bo', '1111-222-333', 'sf bay area')

C'est ce que nous savons:

>>> bob == jim
True

Mais ce sont deux objets différents avec une mémoire différente allouée, tout comme deux enregistrements différents de la même personne:

>>> bob is jim
False

Vient maintenant la partie où hash () est pratique:

>>> dmv_appointments = {}
>>> dmv_appointments[bob] = 'tomorrow'

Devine quoi:

>>> dmv_appointments[jim] #?
'tomorrow'

À partir de deux enregistrements différents, vous pouvez accéder aux mêmes informations. Maintenant, essayez ceci:

>>> dmv_appointments[hash(jim)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in __eq__
AttributeError: 'int' object has no attribute 'ssn'
>>> hash(jim) == hash(hash(jim))
True

Qu'est-ce qui vient de se passer? C'est une collision. Comme hash(jim) == hash(hash(jim)), qui sont tous deux des entiers, nous devons comparer l'entrée de __getitem__ Avec tous les éléments en conflit. L'intégré int n'a pas d'attribut ssn, donc il se déclenche.

>>> del Person.__eq__
>>> dmv_appointments[bob]
'tomorrow'
>>> dmv_appointments[jim]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: <__main__.Person object at 0x7f611bd37110>

Dans ce dernier exemple, je montre que même avec une collision, la comparaison est effectuée, les objets ne sont plus égaux, ce qui signifie qu’elle soulève avec succès un KeyError.

25
dnozay

Le Python docs pour hash() ) == état:

Les valeurs de hachage sont des entiers. Ils sont utilisés pour comparer rapidement les clés du dictionnaire lors d’une recherche dans le dictionnaire.

Les dictionnaires Python sont implémentés sous forme de tables de hachage. Ainsi, chaque fois que vous utilisez un dictionnaire, hash() est appelée sur les clés que vous transmettez pour affectation ou recherche.

De plus, le docs pour le type dict :

Les valeurs qui ne sont pas hashable , c'est-à-dire les valeurs contenant des listes, des dictionnaires ou d'autres types mutables (qui sont comparées par valeur plutôt que par identité d'objet) ne peuvent pas être utilisé comme clé.

2
Jonathon Reinhart

Le hachage est utilisé par les dictionnaires et les ensembles pour rechercher rapidement l’objet. L'article de Wikipedia sur tables de hachage constitue un bon point de départ.

1
NPE

Je le cherche aussi depuis très longtemps. Maintenant, j’ai eu ma réponse, donc je tondais avec vous tous ...

Veuillez utiliser le Dictionnaire le type de données en python, son très très simile au hash ... Son aussi supporté imbriqué, semblable au hachage à imbriqué.

Exemple:-

dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
dict['Age'] = 8; # update existing entry
dict['School'] = "DPS School" # Add new entry

print ("dict['Age']: ", dict['Age'])
print ("dict['School']: ", dict['School'])

Type de données du dictionnaire: - https://www.tutorialspoint.com/python3/python_dictionary.htm

Espère que ça résoud le problème ..

0