【问题标题】:Implement a list wrapper with overridden __cmp__ function使用重写的 __cmp__ 函数实现列表包装器
【发布时间】:2014-11-03 22:44:22
【问题描述】:

我创建了一个新的 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 True)。但我得到了

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

他们像 list 对象本身一样被比较。我做错了什么?

【问题讨论】:

  • 你的 __cmp__ 方法永远不会被调用。
  • 不 cmp
  • 似乎list 实现了所有丰富的比较运算符,即__lt____ge____eq__ 等,因此调用这些运算符而不是__cmp__。猜猜你必须覆盖所有这些。

标签: python python-2.7


【解决方案1】:

你需要实现函数__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)

更新:(以前的代码不能像 cmets 中解释的那样完美运行)

虽然@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()

【讨论】:

  • 这修复了 == 的问题,但不是一般情况下。 &lt;!= 等仍然以 list 中的方式工作。
  • 在 Python 3 中,即使没有基类,似乎也必须实现 __eq__ ——__cmp__ 返回 0 不足以使相等为真,而在 Python 2 中是这样!
  • @JohnZwinck 在 Python3 中,__cmp__ 根本不再使用。见here
  • @tobias_k:很高兴知道,如果代码最终出现在 Python 3 上,OP 可能会对此感兴趣。
【解决方案2】:

问题似乎是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)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-15
    • 2020-08-12
    • 2012-10-06
    • 2017-01-29
    • 2020-05-02
    • 1970-01-01
    • 2018-04-03
    相关资源
    最近更新 更多