【问题标题】:Object equallity in python collections.Counterpython collections.Counter中的对象相等性
【发布时间】:2013-02-02 22:45:39
【问题描述】:

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

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

另一个尝试可能是从 Counter 继承并覆盖底层方法 计数器用于测量对象之间的相等性,我不确定,但我认为 Counter 使用__contains__ 方法。

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

【问题讨论】:

    标签: python dictionary counter object-equality


    【解决方案1】:

    你还必须实现__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})
    

    【讨论】:

      【解决方案2】:

      如果您的对象像示例中一样简单,请使用 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})
      

      【讨论】:

        猜你喜欢
        • 2015-01-05
        • 1970-01-01
        • 2013-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多