使用重写的__cmp__函数实现列表包装器

时间:2014-09-10 10:14:37

标签: python python-2.7

我创建了一个新的Python对象,如下所示

class Mylist(list):
    def __cmp__(self,other):
        if len(self)>len(other):
            return 1
        elif len(self)<len(other):
            return -1
        elif len(self)==len(other):
            return 0

我的意图是,当比较两个Mylist个对象时,具有大量项目的对象应该更高

c=Mylist([4,5,6])
d=Mylist([1,2,3])

运行上述代码后,cd应该相等(c==d&lt; == True )。但我得到了

>>> c==d
False
>>> c>d
True
>>> 

它们与列表对象本身进行比较。我做错了什么?

2 个答案:

答案 0 :(得分:2)

您需要实现函数__eq__

class Mylist(list):
  def __cmp__(self,other):
    if len(self)>len(other):
        return 1
    elif len(self)<len(other):
        return -1
    elif len(self)==len(other):
        return 0
  def __eq__(self, other):
    return len(self)==len(other)

更新:(之前的代码无法完全按照评论中的说明运作)

尽管@tobias_k的答案解释得更好,但如果你坚持的话,可以通过Python 2中的__cmp__函数来解决。您可以通过删除其他比较函数(le,lt,ge,...)来启用

class Mylist(list):
  def __cmp__(self,other):
    if len(self)>len(other):
        return 1
    elif len(self)<len(other):
        return -1
    elif len(self)==len(other):
        return 0
  def __eq__(self, other):
    return len(self)==len(other)
  @property
  def __lt__(self, other): raise AttributeError()
  @property
  def __le__(self, other): raise AttributeError()
  @property
  def __ne__(self, other): raise AttributeError()
  @property
  def __gt__(self, other): raise AttributeError()
  @property
  def __ge__(self, other): raise AttributeError()

答案 1 :(得分:1)

问题似乎是list实现了所有rich comparison operators,而__cmp__将实现only be called if those are not defined。因此,似乎你必须覆盖所有这些:

class Mylist(list):

    def __lt__(self, other): return cmp(self, other) <  0
    def __le__(self, other): return cmp(self, other) <= 0
    def __eq__(self, other): return cmp(self, other) == 0
    def __ne__(self, other): return cmp(self, other) != 0
    def __gt__(self, other): return cmp(self, other) >  0
    def __ge__(self, other): return cmp(self, other) >= 0

    def __cmp__(self, other): return cmp(len(self), len(other))
顺便说一下,看来__cmp__完全在Python 3中删除了。上面的内容适用于Python 2.x,但为了兼容性,你应该更喜欢这样做

    def __lt__(self, other): return len(self) < len(other)

另请参阅这两个related questions。请注意,虽然在Python 3中实现__eq____lt__并且让Python推断其余部分就足够了,但在这种情况下这不起作用,因为list已经实现了所有这些,所以你必须全部覆盖它们。