Syntaxe
object.__hash__(x)
Le Python __hash__()
la méthode implémente le hash()
intégré fonction. Ainsi, lorsque vous appelez le hash(x)
, Python tente d'appeler x.__hash__()
. Si la valeur de retour n'est pas un entier ou le x.__hash__()
méthode n'est pas définie, Python lèvera un TypeError
.
Nous appelons cela une "méthode Dunder" pour "D ouble Sous Méthode de score" (également appelée "méthode magique" ). Pour obtenir une liste de toutes les méthodes de dunder avec des explications, consultez notre article sur la feuille de triche de dunder sur ce blog.
Hachage d'arrière-plan()
hash(object)
intégré de Python La fonction prend un objet comme argument et renvoie sa valeur de hachage sous forme d'entier. Vous pouvez voir cette valeur de hachage comme une empreinte digitale unique de cet objet.
Comme la valeur de hachage est calculée sur la base des données de l'objet, deux objets différents mais égaux doivent avoir la même valeur de hachage. Il ne s'ensuit pas, cependant, que deux objets avec la même valeur de hachage sont égaux :ils peuvent avoir la même valeur de hachage et être toujours différents.
Exemple personnalisé __hash__()
Dans l'exemple suivant, vous créez une classe personnalisée Data
et écrasez le __hash__()
méthode magique pour qu'elle renvoie un entier lors de la tentative d'appel de hash(x)
sur un Data
personnalisé objet.
class Data: def __hash__(self): return 42 x = Data() res = hash(x) print(res) # 42
__hash__() par défaut
Si vous ne définissez pas le __hash__()
méthode magique, Python renverra sa propre valeur de hachage entière car __hash__()
est implémenté pour chaque objet Python.
class Data: pass x = Data() res = hash(x) print(res) # 42
Ceci est la sortie sur mon ordinateur - ce sera probablement différent sur le vôtre car le résultat représente une adresse mémoire spécifique de l'objet :
116229704442
TypeError :la méthode __hash__ doit renvoyer un entier
Si le Python __hash__
fonction ne renvoie pas de valeur entière, Python lèvera le TypeError: __hash__ method should return an integer
en appelant le hash()
sur un objet donné. Pour corriger cette erreur, vous devez modifier la valeur de retour de __hash__()
à une valeur entière.
Considérez l'extrait de code suivant où vous essayez de renvoyer une chaîne dans la méthode dunder __hash__()
:
class Data: def __hash__(self): return 'finxter' x = Data() res = hash(x) print(res)
L'exécution de cette opération entraîne le message d'erreur suivant sur mon ordinateur :
Traceback (most recent call last): File "C:\Users\xcent\Desktop\code.py", line 7, in <module> res = hash(x) TypeError: __hash__ method should return an integer
Bonnes pratiques __hash__
Certaines exigences doivent être satisfaites lors de la mise en œuvre de votre propre __hash__()
personnalisé méthode. Je vais les énumérer ici sous forme de liste à puces :
- La valeur renvoyée doit être un entier.
- Les objets comparables ont la même valeur de hachage. Donc, si
x==y
, il devrait s'ensuivre quex.__hash__() == y.__hash__()
. Il s'ensuit que si une classe ne définit pas__eq__()
pour vérifier l'égalité, il ne doit pas implémenter__hash__()
Soit. - La valeur de retour de
x.__hash__()
est tronqué à 4-8 octets lors de l'appel dehash(x)
, alors assurez-vous de ne pas perdre accidentellement ces informations. Vous pouvez voir que les sorties diffèrent pour les entiers énormes ici :
class Data: def __hash__(self): return 99999999999999999999999999999999999999999999999999 x = Data() res = hash(x) print(res) # 619332571178673745
- Le
__hash__
La méthode sur un objet donné renvoie souvent le résultat de la mise de l'état de l'objet, c'est-à-dire ses valeurs d'attribut, dans un tuple et du hachage du tuple. Voici un exemple :
class Person: def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex def __hash__(self): return hash((self.name, self.age, self.sex)) ann = Person('Ann', 23, 'w') ann_2 = Person('Ann', 23, 'w') alice = Person('Alice', 33, 'w') print(hash(ann)) print(hash(ann_2)) print(hash(alice))
La sortie montre que les deux premiers objets, bien que différentes instances, produisent la même valeur de hachage :
5084601898576458507 5084601898576458507 -1197787602517711359
Références :
- https://docs.python.org/3/reference/datamodel.html
- https://docs.python.org/3.5/reference/datamodel.html#object.__hash__