请考虑以下代码段:
class SomeClass(object):
def __init__(self, someattribute="somevalue"):
self.someattribute = someattribute
def __eq__(self, other):
return self.someattribute == other.someattribute
def __ne__(self, other):
return not self.__eq__(other)
list_of_objects = [SomeClass()]
print(SomeClass() in list_of_objects)
set_of_objects = set([SomeClass()])
print(SomeClass() in set_of_objects)
评估为:
True
False
有人可以解释为什么'in'关键字对集合和列表有不同的含义吗? 我希望两者都返回True,特别是当被测试的类型定义了相等的方法时。
答案 0 :(得分:16)
含义相同,但实施方式不同。列表只是检查每个对象,检查是否相等,因此它适用于您的类。设置对象的第一个哈希值,如果它们没有正确实现哈希,则该集合似乎不起作用。
您的班级定义了__eq__
,但没有定义__hash__
,因此无法正确使用集合或作为词典的键。 __eq__
和__hash__
的规则是__eq__
为True的两个对象也必须具有相等的哈希值。默认情况下,对象根据其内存地址进行哈希。因此,根据您的定义,您的两个对象不会提供相同的哈希值,因此会违反有关__eq__
和__hash__
的规则。
如果您提供__hash__
实施,它将正常工作。对于您的示例代码,它可能是:
def __hash__(self):
return hash(self.someattribute)
答案 1 :(得分:3)
在几乎任何哈希表实现中,包括Python,如果覆盖相等方法,则必须覆盖哈希方法(在Python中,这是__hash__
)。列表的in
运算符只检查与列表中每个元素的相等性,集合的in
运算符首先散列您要查找的对象,检查哈希表的该槽中的对象,以及如果插槽中有任何内容,则检查是否相等。因此,如果您覆盖__eq__
而不覆盖__hash__
,则无法保证集合的in
运算符会检入正确的广告位。
答案 2 :(得分:1)
定义与您的__hash__()
方法相对应的__eq__()
方法。 Example