关于python:使用重写的__cmp__函数实现一个列表包装器

Implement a list wrapper with overridden __cmp__ function

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

1
2
3
4
5
6
7
8
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对象进行比较时,具有大量项目的对象应该更高。

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

运行上述代码后,cd应该相等(c==d<=true)。但是我得到了

1
2
3
4
5
>>> c==d
False
>>> c>d
True
>>>

它们就像列表对象本身一样被比较。我做错了什么?


您需要实现函数__eq__

1
2
3
4
5
6
7
8
9
10
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 answer可以更好地解释这一点,但如果您坚持的话,您可以通过python 2中的__cmp__函数来实现。您可以通过删除其他比较函数(le、lt、ge…)来启用它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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()


问题似乎是list实现了所有的富比较运算符,只有在没有定义这些运算符的情况下才会调用__cmp__。因此,您似乎必须覆盖所有这些内容:

1
2
3
4
5
6
7
8
9
10
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))

顺便说一句,似乎在python 3中完全删除了__cmp__。上面的代码适用于python 2.x,但是为了兼容性,您可能更愿意这样做。

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

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