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


83

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

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

这是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调用的不是集合所调用的方法。叫什么 我还必须定义什么其他方法?

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


1
遇到了同样的问题。我假设您正在代码中处理少量数据。这可能不是使用数据库的理想选择。我记得能够在C ++中创建一个集合并定义一个比较器函数,并且我相信Java也是如此,但是您似乎无法使用Python中的字典对象来做到这一点。似乎有人在Python中编写了一个“设置”库就可以做到这一点,但我还不知道。
克里斯·杜特罗

Answers:


32

恐怕您将不得不提供一种__hash__()方法。但是您可以这样编写代码,即它不依赖于您的可变属性Item


3
< docs.python.org/reference/… >在此处的第二段中,指出__hash__()仅应为不可变对象定义。
阿达(Ada)2010年

1
@Nathanael:如果可能需要更改对象,则可以制作该对象的不变副本,例如Frozenset()和set()。
Lie Ryan 2010年

2
@Nathanael-您想怎么打__eq__?比较那些(1,2)属性?然后,您还必须在方法中返回(1,2)的哈希值__hash__
eumiro 2010年

还是因为foo和bar都是不可变的,所以__hash __()可以返回foo和bar的哈希值之和?不...总和太不可靠了...如果foo为1且bar为2,那等于bar为1,而foo为2,这是错误的。为此可以使用什么数学函数?模数或除法应该起作用。
阿达(Ada)2010年

1
Nathanael:只需使用hash内置的:hash((self.foo, self.bar))。这使用了适合您需要的元组哈希。(您__eq__也可以用tuple比较的方式来写。)
Pi Delport,2010年

73

是的,您需要一个__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__())

3
在Python 3中,你并不需要__ne__,甚至在2.x中,你不应该定义__ne__来讲__eq__。请参阅stackoverflow.com/a/30676267/5337834
John Strood,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.