Python 2:集合和列表的'in'关键字的不同含义

时间:2012-02-13 04:02:36

标签: python list set equality

请考虑以下代码段:

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,特别是当被测试的类型定义了相等的方法时。

3 个答案:

答案 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