Python set([]) 如何检查两个对象是不是相等?一个对象需要定义哪些方法来自定义它?

Posted

技术标签:

【中文标题】Python set([]) 如何检查两个对象是不是相等?一个对象需要定义哪些方法来自定义它?【英文标题】:How does a Python set([]) check if two objects are equal? What methods does an object need to define to customise this?Python set([]) 如何检查两个对象是否相等?一个对象需要定义哪些方法来自定义它? 【发布时间】:2011-04-25 22:22:33 【问题描述】:

我需要在 Python 中创建一个“容器”对象或类,它会记录我还定义的其他对象。此容器的一个要求是,如果两个对象被认为是相同的,则删除一个(其中一个)。我的第一个想法是使用set([]) 作为包含对象,来完成这个要求。

但是,该集合不会删除两个相同的对象实例之一。我必须定义什么来创建一个?

这是 Python 代码。

class Item(object):
  def __init__(self, foo, bar):
    self.foo = foo
    self.bar = bar
  def __repr__(self):
    return "Item(%s, %s)" % (self.foo, self.bar)
  def __eq__(self, other):
    if isinstance(other, Item):
      return ((self.foo == other.foo) and (self.bar == other.bar))
    else:
      return False
  def __ne__(self, other):
    return (not self.__eq__(other))

口译员

>>> set([Item(1,2), Item(1,2)])
set([Item(1, 2), Item(1, 2)])

很明显,x == y调用的__eq__()不是set调用的方法。什么叫做?我还必须定义什么其他方法?

注意:Items 必须保持可变,并且可以更改,因此我无法提供 __hash__() 方法。如果这是唯一的方法,那么我将重写以使用不可变的Items。

【问题讨论】:

遇到了同样的问题。我假设您正在处理代码中的少量数据。这可能不是使用数据库的好选择。我记得能够在 C++ 中创建一个集合并定义一个比较器函数,我也相信 Java,但是看起来你不能用 Python 中的字典对象来做到这一点。似乎有人可能已经用 Python 编写了一个可以做到这一点的“集合”库,但我不知道有一个。 【参考方案1】:

是的,您需要一个 __hash__()-method 和您已经提供的比较运算符。

class Item(object):
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar
    def __repr__(self):
        return "Item(%s, %s)" % (self.foo, self.bar)
    def __eq__(self, other):
        if isinstance(other, Item):
            return ((self.foo == other.foo) and (self.bar == other.bar))
        else:
            return False
    def __ne__(self, other):
        return (not self.__eq__(other))
    def __hash__(self):
        return hash(self.__repr__())

【讨论】:

在 Python 3 上,您不需要 __ne__,即使在 2.x 中,您也不应该根据 __eq__ 定义 __ne__。见,***.com/a/30676267/5337834【参考方案2】:

恐怕您必须提供__hash__() 方法。但是你可以这样编码,它不依赖于你的Item的可变属性。

【讨论】:

docs.python.org/reference/…>这里的第二段指出__hash__()应该只为不可变对象定义。 @Nathanael:如果对象可能需要更改,您可以制作对象的不可变副本,例如 freezeset() 和 set()。 @Nathanael - 你想怎么打电话给__eq__?比较那些(1,2)属性?然后,您还必须在 __hash__ 方法中返回一些 (1,2) 的哈希值。 或者,既然 foo 和 bar 都是不可变的,那么 __hash__() 可以返回 foo 和 bar 的哈希值之和吗?不... sum 太不可靠了... 如果 foo 是 1 和 bar 2,那将等于 bar 为 1 而 foo 为 2,这是错误的。什么数学函数可以用于此目的?模数或除法应该可以工作。 Nathanael:只需使用 hash 内置函数:hash((self.foo, self.bar))。这使用元组的散列,这适合您的需要。 (您的__eq__ 也可以写成tuple 比较。)

以上是关于Python set([]) 如何检查两个对象是不是相等?一个对象需要定义哪些方法来自定义它?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 unordered_set 是不是重叠?

Spring Data JPA 检查 SET 是不是包含对象

如何检查 Python 中是不是同时存在两个变量? [复制]

如何检查一个对象在 Python 中是不是可迭代? [复制]

我如何检查属性是不是在更新前实际更改

如何检查两个对象是不是具有相同的一组属性名称?