python collections.Counter中的对象equallity

ang*_*lar 3 python counter dictionary object-equality

我有和collection.Counter类的实例,我也有一些对象,如:

p1 = Person(name='John')
p2 = Person(name='John')
p3 = Person(name='Jane')
Run Code Online (Sandbox Code Playgroud)

我想在Counter的一个实例中保存此person对象的计数,考虑到具有相同名称的person对象必须增加相同的人数,所以如果我有一个包含所有person对象的列表:

people = [p1, p2, p3]
Run Code Online (Sandbox Code Playgroud)

我用它填充我的柜台:

c = Counter(people)
Run Code Online (Sandbox Code Playgroud)

我想得到以下内容:

c[p1] #prints 2
c[p2] #prints 2
c[p3] #prints 1
Run Code Online (Sandbox Code Playgroud)

我的第一次尝试是__eq__为person对象实现一个新方法

def __eq__(self, other):
  return self.name == other.name
Run Code Online (Sandbox Code Playgroud)

我认为这可以工作,因为计数器对象似乎基于关键对象的相等性增加了键的计数,如:

c = Counter(['A', 'A', 'B'])
c['A'] #prints 2
c['B'] #prints 1
Run Code Online (Sandbox Code Playgroud)

另一个尝试可以从Counter继承并覆盖Counter用于测量对象之间相等性的基础方法,我不确定但我认为Counter使用__contains__方法.

我的问题是,如果有任何方法可以在不使用继承的情况下获得此行为,如果没有,那么最好的方法是什么呢?

Ble*_*der 7

你还必须实现__hash__:

class Person(object):
    def __init__(self, name=None, address=None):
        self.name = name
        self.address = address

    def __eq__(self, other):
        return self.name == other.name and self.address == other.address

    def __hash__(self):
        return hash((self.name, self.address))
Run Code Online (Sandbox Code Playgroud)

现在您的代码有效:

>>> Counter(people)
Counter({<__main__.Person object at 0x24a7590>: 2, <__main__.Person object at 0x24a75d0>: 1})
Run Code Online (Sandbox Code Playgroud)