我有集合的实例。计数器类,我也有一些对象,例如:
p1 = Person(name='John')
p2 = Person(name='John')
p3 = Person(name='Jane')
我想在 Counter 实例中保存此人员对象的计数,考虑到具有相同名称的人员对象必须增加相同的人员计数,因此,如果我有一个包含所有人员对象的列表:
people = [p1, p2, p3]
我用它填充我的计数器:
c = Counter(people)
我想得到以下内容:
c[p1] #prints 2
c[p2] #prints 2
c[p3] #prints 1
我的第一次尝试是为 person 对象实现一种新的 __eq__
方法
def __eq__(self, other):
return self.name == other.name
我认为这可以工作,因为计数器对象似乎增加了计数对于基于键对象相等的键,例如:
c = Counter(['A', 'A', 'B'])
c['A'] #prints 2
c['B'] #prints 1
另一种尝试可以从计数器继承并覆盖基础方法用于测量对象之间相等性的计数器用途,我不确定,但我认为计数器为此使用__contains__
方法。
我的问题是,是否有任何方法可以在不使用继承的情况下获得此行为,如果没有,最好的方法是什么?
您还必须实现__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))
现在您的代码可以正常工作:
>>> Counter(people)
Counter({<__main__.Person object at 0x24a7590>: 2, <__main__.Person object at 0x24a75d0>: 1})
如果您的对象像您的示例中一样简单,请使用 collections.namedtuple
from collections import Counter, namedtuple
Person = namedtuple('Person','name')
n1 = Person(name='John')
n2 = Person(name='John')
n3 = Person(name='Jane')
Counter((n1,n2,n3))
# Counter({Person(name='John'): 2, Person(name='Jane'): 1})