简体   繁体   English

python collections.Counter中的对象equallity

[英]Object equallity in python collections.Counter

I have and instance of collections.Counter class, also i have some objects like: 我有和collection.Counter类的实例,我也有一些对象,如:

p1 = Person(name='John')
p2 = Person(name='John')
p3 = Person(name='Jane')

I want to hold the counts for this person objects in a instance of Counter, taking into account that person objects with same names must increment the same person count, so if i have a list with all person objects: 我想在Counter的一个实例中保存此person对象的计数,考虑到具有相同名称的person对象必须增加相同的人数,所以如果我有一个包含所有person对象的列表:

people = [p1, p2, p3]

and i populate my counter with it: 我用它填充我的柜台:

c = Counter(people)

i want to get the following: 我想得到以下内容:

c[p1] #prints 2
c[p2] #prints 2
c[p3] #prints 1

My first attempt was to implement a new __eq__ method for person objects 我的第一次尝试是为person对象实现一个新的__eq__方法

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

I thought that this could work because counter objects seems like increment the counts for keys based on the equality of the key objects, like in: 我认为这可以工作,因为计数器对象似乎基于关键对象的相等性增加了键的计数,如:

c = Counter(['A', 'A', 'B'])
c['A'] #prints 2
c['B'] #prints 1

Another attempt could be inherit from Counter and override the underlying method that Counter uses for measure the equality between objects , i am not sure but i think Counter uses __contains__ method for that. 另一个尝试可以从Counter继承并覆盖Counter用于测量对象之间相等性的基础方法,我不确定但我认为Counter使用__contains__方法。

My question is if there are any way to gets this behavior without using inheritance and if not, what could be the best way to do it?. 我的问题是,如果有任何方法可以在不使用继承的情况下获得此行为,如果没有,那么最好的方法是什么呢?

You also have to implement __hash__ : 你还必须实现__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))

Now your code works: 现在您的代码有效:

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

If your objects are simple as in your example use collections.namedtuple 如果您的对象很简单,请使用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})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM