Python集合如何检查两个对象是否相等?对象需要定义哪些方法来进行自定义?

105 投票
2 回答
63688 浏览
提问于 2025-04-16 05:32

我需要在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)])

很明显,__eq__() 方法是通过 x == y 被调用的,但集合并没有调用这个方法。那么它调用的是什么呢?我还需要定义什么其他的方法呢?

注意:这些 Item 对象必须是可变的,可以改变,所以我不能提供一个 __hash__() 方法。如果这是唯一的解决办法,那我就会考虑使用不可变的 Item 对象。

2 个回答

81

是的,你需要一个 __hash__() 方法,还有你已经提供的比较操作符。

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__())
40

我担心你需要提供一个 __hash__() 方法。不过你可以写这个方法,让它不依赖于你 Item 类中那些可变的属性。

撰写回答