Python:使用集合检测重复项

Cha*_*l72 7 python set python-3.x

我有大量的对象需要存储在内存中以便在Python中进行处理.具体来说,我正在尝试从大量对象中删除重复项.如果对象中的某个实例变量相等,我想将两个对象视为"相等".因此,我认为最简单的方法是将所有对象插入到一个集合中,并覆盖该__hash__方法,以便它散列我关注的实例变量.

所以,作为测试我尝试了以下内容:

class Person:
    def __init__(self, n, a):
        self.name = n
        self.age = a

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

    def __str__(self):
        return "{0}:{1}".format(self.name, self.age)

myset = set()
myset.add(Person("foo", 10))
myset.add(Person("bar", 20))
myset.add(Person("baz", 30))
myset.add(Person("foo", 1000)) # try adding a duplicate

for p in myset: print(p)
Run Code Online (Sandbox Code Playgroud)

在这里,我定义了一个Person类,并且Person具有相同name变量的任何两个实例都是相等的,而不管任何其他实例变量的值.不幸的是,这个输出:

baz:30
foo:10
bar:20
foo:1000
Run Code Online (Sandbox Code Playgroud)

请注意,foo出现两次,因此该程序未能注意到重复.然而,表达hash(Person("foo", 10)) == hash(Person("foo", 1000))True.那么为什么这不能正确检测重复的Person对象呢?

Ign*_*ams 11

你忘了 定义了__eq__().

如果一个类没有定义一个__cmp__()或一个__eq__()方法,它也不应该定义一个__hash__()操作; 如果它定义__cmp__()__eq__()不定义__hash__(),它的实例将不能在散列集合中使用.如果一个类定义了可变对象并实现了一个__cmp__()__eq__()方法,那么它就不应该实现__hash__(),因为hashable集合实现要求对象的散列值是不可变的(如果对象的散列值改变,它将在错误的散列桶中).

  • 解释是由于:如果`o1 == o2`,则集合认为对象相等.散列函数仅用于将对象分布在散列表的桶中,因此只需要对具有相同散列(最终位于同一个桶中)的对象进行相等性比较.因此,对于`dict`和`set`来工作,哈希函数必须满足条件`x == y` =>`hash(x)== hash(y)`,但是oposite(`hash(x)== hash (y)`=>`x == y`)永远不会是真的. (3认同)