2011-03-08 1 views
8

J'ai du mal à comprendre pourquoi la première de ces assertions est OK et la seconde soulève une erreur.En quoi les tests d'appartenance sont-ils différents pour une liste et un ensemble?

subject_list = [Subject("A"), Subject("B"), Subject("C")] 
subject_set = set() 
subject_set.add(Subject("A")) 
subject_set.add(Subject("B")) 
subject_set.add(Subject("C")) 

self.assertIn(Subject("A"), subject_list) 
self.assertIn(Subject("A"), subject_set) 

Voici l'erreur:

Traceback (most recent call last): 
    File "C:\Users\...\testSubject.py", line 34, in testIn 
    self.assertIn(Subject("A"), subject_set) 
AssertionError: <Subject: A> not found in set([<Subject: B>, <Subject: C>, <Subject: A>]) 

Le test pour l'égalité dans la classe Le sujet est tout simplement self.name == other.name, et dans un autre UnitTest Je confirme que Subject("A") == Subject("A"). Je ne peux vraiment pas comprendre pourquoi le sujet est dans la liste et pas dans l'ensemble. Idéalement, j'aimerais que le sujet soit dans les deux.

Répondre

11

L'expression

Subject("A") in subject_list 

va comparer Subject("A") à chaque entrée dans subject_list en utilisant la méthode Subject.__eq__(). Si cette méthode n'est pas remplacée, elle renvoie par défaut False à moins que les deux opérandes soient même objet. L'expression ci-dessus retournera toujours False si Subject manquait d'une méthode __eq__(), puisque Subject("A") est une nouvelle instance qui ne peut pas déjà être dans la liste.

L'expression

Subject("A") in subject_set 

au contraire utilisera Subject.__hash__() premier à trouver le seau à droite et utilisez Subject.__eq__() seulement après cela. Si vous n'avez pas défini Subject.__hash__() d'une manière compatible avec Subject.__eq__(), cela échouera.

+0

Merci! L'implémentation d'une fonction __hash __() dans la classe Subject a résolu ce problème. – rtclay

2

Pour les utiliser dans un ensemble, vous devez vous assurer que Subject est correctement lavable. Si vous ne définissez pas __hash__ vous-même, il faudra simplement prendre le id, et cela est différent pour différentes instances. __hash__ doit être défini de sorte que les objets égaux aient des hachages égaux.

3

Soit vous n'avez pas de méthode __hash__() dans votre classe Subject, soit il est douteux. Essayez ceci:

def __hash__(self): 
    return hash(self.name) 

Les documents sont here.

4

L'appartenance à un ensemble dépend également du hachage de l'objet et, en tant que tel, vous devez implémenter la méthode __hash__() sur la classe de façon appropriée.

Questions connexes