À l'aide de l'objet en tant que clé du dictionnaire en Python - fonction de Hachage
Je suis en train d'utiliser un objet comme valeur de la clé pour un dictionnaire en Python. J'ai suivi les recommandations de certains autres postes dont nous avons besoin pour mettre en œuvre 2 fonctions: de hachage et eq
Et avec qui, j'attends la suite de travailler, mais il n'a pas.
class Test:
def __init__(self, name):
self.name = name
def __hash__(self):
return hash(str(self.name))
def __eq__(self, other):
return str(self.name) == str(other,name)
def TestMethod():
test_Dict = {}
obj = Test('abc')
test_Dict[obj] = obj
print "%s" %(test_Dict[hash(str('abc'))].name) # expecting this to print "abc"
Mais il me donne une clé de message d'erreur:
KeyError: 1453079729188098211
Quelqu'un peut-il aider à éclairer moi pourquoi cela ne fonctionne pas?
- Quelle est la version de Python que vous utilisez?
return str(self.name) == str(other,name)
a apparemment un bug dansstr(other,name)
je ne comprends pas comment ce n'est pas soulevée. Même si c'eststr(other.name)
il ne fonctionne pas carhash(str('abc'))
n'a pas.name
attribut
Vous devez vous connecter pour publier un commentaire.
Éléments d'une cartographie des pas accessibles par leur hachage, même si leur valeur de hachage est utilisée pour les placer à l'intérieur de la cartographie. Vous doit utiliser la même valeur lors de l'indexation à la fois pour le stockage et pour la recherche.
Vous n'avez pas besoin de redéfinir
hash
eteq
d'utiliser un objet comme clé de dictionnaire.Cela fonctionne bien et imprimer
abc
.Comme expliqué par Ignacio Vazquez-Abrams vous n'utilisez pas la table de hachage de l'objet, mais l'objet lui-même comme la clé pour accéder à la valeur de dictionnaire.
Les exemples que vous avez trouvé comme python: mes classes comme dict clés. comment? ou Objet de type personnalisé en tant que clé de dictionnaire redéfinir
hash
eteq
pour un but spécifique.Par exemple tenir compte de ces deux objets
obj = Test('abc')
etobj2 = Test('abc')
.Cela permettra de jeter un
KeyError
exception car obj et obj2 ne sont pas le même objet.Cette impression
abc
.obj
etobj2
sont encore à des objets différents, mais maintenant ils ont le même hash, et sont évaluées comme des égaux quand on les compare.Explication Des Erreurs
Donné le code fourni dans le post, je n'ai pas vraiment de voir comment vous obtenez le KeyError parce que vous devriez recevoir un AttributeError (en supposant que le
str(other,name)
était une faute de frappe destinée à êtrestr(other.name)
). Le AttributeError vient de la__eq__
méthode lorsque l'on compare le nom de l'autonomie contre le nom de l'autre parce que votre clé pendant la recherche,hash(str('abc'))
, est un int/long, pas unTest
objet.Lors de la recherche d'une clé dans un dict, la première opération consiste à obtenir le hash de la clé à l'aide de la clé
__hash__
méthode. Deuxièmement, si une valeur de hachage existe dans le dict, le__eq__
méthode de la clé est appelé à comparer la clé contre n'importe quelle valeur a été trouvé. C'est pour s'assurer que, dans le cas des objets avec le même hachage sont stockés dans le dict (via open adressage), l'objet est récupéré. En moyenne, cette recherche est toujours en O(1).En regardant ce une étape à la fois, le hachage de
hash(str('abc'))
etobj
sont les mêmes. DansTest
, vous définissez__hash__
que le hash d'une chaîne de caractères. Lors de l'exécution de recherche avectest_Dict[hash(str('abc'))]
, vous êtes réellement à la recherche de la hash de hash, mais c'est quand même très bien, puisque la valeur de hachage d'un int est lui-même en python.Lors de la comparaison de ces deux valeurs en fonction de votre défini
__eq__
méthode, vous pouvez comparer les noms des objets, mais la valeur de la comparaison de contre est un int (hash(str('abc'))
), qui n'ont pas dename
de la propriété, de sorte que le AttributeError est soulevée.Solution
Tout d'abord, vous ne devez pas (et ne doivent) appel
hash()
lors de l'exécution de la réelle dict recherche depuis cette clé est également transmis en tant que second argument de votre__eq__
méthode. Doncdevrait devenir
ou tout simplement
depuis l'appel de
str()
sur une chaîne littérale n'a pas beaucoup de sens.Deuxièmement, vous aurez besoin de modifier votre
__eq__
méthode telle qu'elle prend en compte le type de laother
objet de la comparaison de contre. Vous avez différentes options pour cette fonction sur ce qui va être stocké dans le même dict avec votreTest
instances clés.Si vous prévoyez de stocker votre
Test
cas dans un dictionnaire uniquement avec d'autresTest
s (ou tous les objets qui ont unename
de la propriété), vous pouvez continuer ce que vous avez actuellementpuisque vous garantir que tous les autres clés de la comparaison de contre dans le dict est de type
Test
et a unname
.Si vous prévoyez de mélanger votre
Test
cas dans un dictionnaire avec juste des chaînes, vous devrez vérifier si l'objet vous comparer est une chaîne de caractères ou non, puisque les chaînes n'ont pas dename
propriété en python.Si vous prévoyez d'utiliser comme les touches d'un mélange de
Test
s et les autres types d'objets, vous aurez besoin de vérifier si laother
objet a unename
à comparer.Je ne suis pas un grand fan de la dernière 2 depuis quelque sorte, d'aller à contre-duck-typing en python avec ceux-ci, mais il y a toujours des exceptions dans la vie.