J'ai un grand nombre d'objets que je dois stocker en mémoire pour le traitement de Python. Plus précisément, j'essaie d'éliminer les doublons d'un grand ensemble d'objets. Je tiens à considérer deux objets "égaux" si une certaine variable d'instance dans l'objet est égale. Donc, j'ai supposé que le moyen le plus simple de le faire serait d'insérer tous mes objets dans un ensemble et de remplacer la méthode , en tant que test, j'ai essayé ce qui suit: p> ici, je définis une classe Notez que __ de hachage __ code> de sorte qu'il heurte la variable d'instance dont je suis concerné.
personne code> et deux instances de
personne Code> avec le même nom code> La variable code> doit être égal, quelle que soit la valeur de toute autre variable d'instance. Malheureusement, ces sorties: p>
foo code> apparaît deux fois, ce programme n'a donc pas remarqué des doublons. Pourtant, l'expression
hachage (personne ("foo", 10)) == hachage (personne ("foo", 1000)) code> est
vrai code>. Alors, pourquoi cela ne détecte-t-il pas correctement les objets code> personne code>? P> p>
5 Réponses :
Vous avez oublié de aussi em> Définir Si une classe ne définit pas un __ eq __ () code >
. p>
__ cmp __ () code> ou
__ eq __ () code> méthode Il ne faut pas définir un
__ hachage __ () code> Opération; S'il définit
__ cmp __ () code> ou
__ eq __ () code> mais pas
__ hachage __ () code>, ses instances ne seront pas utilisables dans des collections hachées. Si une classe définit des objets mutables et implémente un
__ cmP __ () code> ou
__ eq __ () code> méthode, il ne doit pas implémenter
__ hachage __ () code>, depuis la collecte de hachable Les implémentations exigent que la valeur de hachage d'un objet soit immuable (si la valeur de hachage de l'objet change, il sera dans le mauvais godet de hachage). P>
blockQuote>
L'explication est due: l'ensemble considère les objets égaux si o1 == o2 code>. La fonction de hachage n'est utilisée que pour étaller les objets sur les godets de la table de hachage, alors seuls les objets avec le même hachage (qui se retrouvent dans le même godet) doivent être comparés à l'égalité. Ainsi, pour
dict code> et
définir code> pour fonctionner la fonction de hachage doit satisfaire la condition
x == y code> =>
hachage (x) == hachage (Y) code>, mais l'oposite (
hachage (x) == hachage (y) code> =>
x == y code>) n'est jamais vrai.
La fonction de hachage ne suffit pas à distinguer l'objet que vous devez implémenter la fonction de comparaison (c'est-à-dire. __ eq __ code>). P>
Un ensemble devra évidemment faire face aux collisions de hachage. Si le hachage de deux objets correspond, l'ensemble les comparera à l'aide de l'opérateur histoire longue courte: définissez également == code> pour vous assurer qu'ils sont vraiment égaux. Dans votre cas, cela ne produira que
true code> si les deux objets sont le même objet (la mise en œuvre standard pour les classes définies par l'utilisateur). P>
__ eq __ () code> pour le faire fonctionner. P>
Vous avez également besoin de la méthode __ EQ __ (). P>
une fonction de hachage dit efficacement "A peut-être égale à B" ou "A non égal à B (à coup sûr)".
S'il est dit "peut-être égale" puis l'égalité doit être vérifiée de toute façon pour s'assurer, c'est pourquoi Vous devez également implémenter Néanmoins, définissant La fonction de hachage doit toutefois toujours suivre la "règle de hachage": p> Par exemple, vous pouvez tout hash tout par Notez que votre chemin est toujours correct. Il aurait cependant été une erreur de codage à utiliser __ eq __ code>. p>
__ hachage __ code> vécu de manière significative les choses en faisant de manière significative en faisant "un B (non égal à B (à certitude)" un
o (1) code> opération. p>
def __hash __ (auto): retour 1 code>. Cela serait toujours correct, mais il serait inefficace car vous devriez vérifier
__ eq __ code> à chaque fois, ce qui peut être un processus long si vous avez des structures de données importantes compliquées (par exemple avec de grandes listes, des dictionnaires, des dictionnaires, etc Si Bob est une personne de 20 ans et que Bob est une autre personne de 30 ans et sont des personnes différentes (probablement à moins que ce soit une sorte de maintien de la piste-de-peu-la-personne - du programme à l'origine), puis Ils seront hachés à la même valeur et doivent être comparés à
__ eq __ code>. C'est parfaitement bien, mais je l'implémenterais comme: p>
hachage ((auto.name, self.action)) code> dans un monde où
personne ("bob", âge = 20) code> et
personne ("bob", âge = 30) code> était en fait la même personne, car la fonction de hachage indiquerait qu'ils sont différentes, tandis que la fonction égale ne serait pas (mais être ignorée). P > p>