列表和集合的成员测试有什么不同?
我在搞清楚为什么第一个判断是正常的,而第二个却报错时遇到了困难。
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)
这是报错信息:
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>])
在Subject类中,判断两个对象是否相等的方式很简单,就是用 self.name == other.name
。在另一个单元测试中,我验证了 Subject("A") == Subject("A")
是成立的。我真的搞不明白为什么这个主题在列表中,但不在集合里。理想情况下,我希望这个主题能同时出现在这两者中。
4 个回答
3
要么你的Subject
类里没有__hash__()
这个方法,要么这个方法有问题。你可以试试下面的代码:
def __hash__(self):
return hash(self.name)
相关的文档可以在这里找到。
4
一个对象是否属于某个集合,还跟它的哈希值有关。因此,你需要在这个类里正确地实现 __hash__()
方法。
13
这个表达式
Subject("A") in subject_list
会用 Subject.__eq__()
方法将 Subject("A")
和 subject_list
中的每一项进行比较。如果这个方法没有被重写,它默认的行为是总是返回 False
,除非这两个对象是同一个实例。也就是说,如果 Subject
没有 __eq__()
方法,上面的表达式总是会返回 False
,因为 Subject("A")
是一个新的实例,不可能已经在列表里。
而这个表达式
Subject("A") in subject_set
则相反,它会先使用 Subject.__hash__()
方法找到合适的“桶”,然后再使用 Subject.__eq__()
方法进行比较。如果你没有以与 Subject.__eq__()
兼容的方式定义 Subject.__hash__()
,那么这个过程就会失败。