【问题标题】:add object into python's set collection and determine by object's attribute将对象添加到python的集合中并通过对象的属性确定
【发布时间】:2012-05-19 19:30:57
【问题描述】:

我有一个像这样的Person 类:

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

    def __repr__(self):
        return '<Person {}>'.format(self.name)

我想将此类的一些实例添加到集合中,如下所示:

tom = Person('tom', 18)
mary = Person('mary', 22)
mary2 = Person('mary2', 22)

person_set = {tom, mary, mary2}
print(person_set)
# output: {<Person tom>, <Person mary>, <Person mary2>}

如您所见,集合中有 2 个玛丽。我怎样才能使具有相同年龄的Person 实例被视为同一个人,并且只添加到集合中一次?

换句话说,我怎样才能得到{&lt;Person tom&gt;, &lt;Person mary&gt;}的结果?

【问题讨论】:

  • 那么,例如,如果您只是按年龄进行比较,Frank, age 19 会与 Heather, age 19 相同吗?
  • 是的,只有第一个添加到集合中的才会被存储
  • @sashimi,那么你需要一个以年龄为键,以Person对象为值的字典。
  • @spinlok 我认为他只需要实现__hash__

标签: python set


【解决方案1】:

当一个新对象被添加到 Python 集合中时,首先计算对象的哈希码,然后,如果集合中已经有一个或多个具有相同哈希码的对象,则测试这些对象与新对象相等。

这样做的结果是你需要在你的类上实现__hash__(...)__eq__(...) 方法。例如:

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

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

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

    def __repr__(self):
        return '<Person {}>'.format(self.name)

tom = Person('tom', 18)
mary = Person('mary', 22)
mary2 = Person('mary2', 22)

person_set = {tom, mary, mary2}
print(person_set)
# output: {<Person tom>, <Person mary>}

但是,您应该非常仔细地考虑 __hash____eq__ 的正确实现对于您的班级应该是什么。上面的示例有效,但没有意义(例如,__hash____eq__ 均仅根据年龄定义)。

【讨论】:

  • 谢谢~这就是我想要的,我知道这很奇怪。我将使用的像 Person 这样的类非常简单。所以无论是覆盖还是覆盖都没有关系不,我知道它不受欢迎^_^,我会小心使用它
  • 如果python已经在比较__hash__中指定的值,为什么还要指定__eq__方法?
  • 我回答了我自己的评论 - docs.python.org/3/glossary.html#term-hashable __hash__ 用于“对象”的生命周期值,__eq__ 用于与其他对象进行比较。您仍然需要两者进行比较
  • hynek.me/articles/hashes-and-equality 是一篇了解更多背景的好文章
猜你喜欢
  • 2015-11-15
  • 2019-10-01
  • 2015-09-21
  • 1970-01-01
  • 2014-12-09
  • 1970-01-01
  • 2019-12-27
  • 1970-01-01
相关资源
最近更新 更多