为什么我不能像使用Python 2一样使用Python 3中的__cmp__方法呢?

时间:2021-02-28 06:52:52

The following piece of code

下面这段代码

class point:    def __init__(self, x, y):        self.x = x        self.y = y    def dispc(self):        return ('(' + str(self.x) + ',' + str(self.y) + ')')    def __cmp__(self, other):        return ((self.x > other.x) and (self.y > other.y))

works fine in Python 2, but in Python 3 I get an error:

在Python 2中工作得很好,但是在Python 3中我得到一个错误:

>>> p=point(2,3)>>> q=point(3,4)>>> p>qTraceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: unorderable types: point() > point()

It only works for == and !=.

它只适用于=和!=。

3 个解决方案

#1


36  

You need to provide the rich comparison methods for ordering in Python 3, which are __lt__, __gt__, __le__, __ge__, __eq__, and __ne__. See also: PEP 207 -- Rich Comparisons.

您需要为Python 3中的订购提供丰富的比较方法,它们是__lt__、__gt__、__le__、__ge__、__eq__和__ne__。参见:PEP 207——丰富的比较。

__cmp__ is no longer used.

不再使用__cmp__。


More specifically, __lt__ takes self and other as arguments, and needs to return whether self is less than other. For example:

更具体地说,__lt__将self和other作为参数,并需要返回self是否小于other。例如:

class Point(object):    ...    def __lt__(self, other):        return ((self.x < other.x) and (self.y < other.y))

(This isn't a sensible comparison implementation, but it's hard to tell what you were going for.)

(这不是一个明智的比较实现,但很难说您想要什么。)

So if you have the following situation:

如果你有以下情况:

p1 = Point(1, 2)p2 = Point(3, 4)p1 < p2

This will be equivalent to:

这将等于:

p1.__lt__(p2)

which would return True.

这将返回True。

__eq__ would return True if the points are equal and False otherwise. The other methods work analogously.

如果点是相等的,则__eq__将返回True。其他的方法也是类似的。


If you use the functools.total_ordering decorator, you only need to implement e.g. the __lt__ and __eq__ methods:

如果您使用函数工具。total_orderdecorator,您只需要实现__lt__和__eq__方法:

from functools import total_ordering@total_orderingclass Point(object):    def __lt__(self, other):        ...    def __eq__(self, other):        ...

#2


10  

This was a major and deliberate change in Python 3. See here for more details.

这是Python 3中一个重大的、深思熟虑的改变。详情请参见这里。

#3


4  

In Python3 the six rich comparison operators

在Python3中,六个比较丰富的比较运算符。

__lt__(self, other) __le__(self, other) __eq__(self, other) __ne__(self, other) __gt__(self, other) __ge__(self, other) 

must be provided individually. This can be abbreviated by using functools.total_ordering.

必须单独提供。可以通过使用functions . total_ordered对其进行缩写。

This however turns out rather unreadable and unpractical most of the time. Still you have to put similar code pieces in 2 funcs - or use a further helper func.

然而,这在大多数时候都是难以读懂和不切实际的。仍然需要将类似的代码片段放入两个函数中——或者使用一个进一步的helper函数。

So mostly I prefer to use the mixin class PY3__cmp__ shown below. This reestablishes the single __cmp__ method framework, which was and is quite clear and practical in most cases. One can still override selected rich comparisons.

因此,我更喜欢使用下面显示的mixin类PY3__cmp__。这重新建立了单一的__cmp__方法框架,这在大多数情况下是非常清晰和实用的。仍然可以覆盖选择的丰富比较。

Your example would just become:

你的例子会变成:

 class point(PY3__cmp__):      ...       # unchanged code

The PY3__cmp__ mixin class:

PY3 = sys.version_info[0] >= 3if PY3:    def cmp(a, b):        return (a > b) - (a < b)    # mixin class for Python3 supporting __cmp__    class PY3__cmp__:           def __eq__(self, other):            return self.__cmp__(other) == 0        def __ne__(self, other):            return self.__cmp__(other) != 0        def __gt__(self, other):            return self.__cmp__(other) > 0        def __lt__(self, other):            return self.__cmp__(other) < 0        def __ge__(self, other):            return self.__cmp__(other) >= 0        def __le__(self, other):            return self.__cmp__(other) <= 0else:    class PY3__cmp__:        pass

#1


36  

You need to provide the rich comparison methods for ordering in Python 3, which are __lt__, __gt__, __le__, __ge__, __eq__, and __ne__. See also: PEP 207 -- Rich Comparisons.

您需要为Python 3中的订购提供丰富的比较方法,它们是__lt__、__gt__、__le__、__ge__、__eq__和__ne__。参见:PEP 207——丰富的比较。

__cmp__ is no longer used.

不再使用__cmp__。


More specifically, __lt__ takes self and other as arguments, and needs to return whether self is less than other. For example:

更具体地说,__lt__将self和other作为参数,并需要返回self是否小于other。例如:

class Point(object):    ...    def __lt__(self, other):        return ((self.x < other.x) and (self.y < other.y))

(This isn't a sensible comparison implementation, but it's hard to tell what you were going for.)

(这不是一个明智的比较实现,但很难说您想要什么。)

So if you have the following situation:

如果你有以下情况:

p1 = Point(1, 2)p2 = Point(3, 4)p1 < p2

This will be equivalent to:

这将等于:

p1.__lt__(p2)

which would return True.

这将返回True。

__eq__ would return True if the points are equal and False otherwise. The other methods work analogously.

如果点是相等的,则__eq__将返回True。其他的方法也是类似的。


If you use the functools.total_ordering decorator, you only need to implement e.g. the __lt__ and __eq__ methods:

如果您使用函数工具。total_orderdecorator,您只需要实现__lt__和__eq__方法:

from functools import total_ordering@total_orderingclass Point(object):    def __lt__(self, other):        ...    def __eq__(self, other):        ...

#2


10  

This was a major and deliberate change in Python 3. See here for more details.

这是Python 3中一个重大的、深思熟虑的改变。详情请参见这里。

#3


4  

In Python3 the six rich comparison operators

在Python3中,六个比较丰富的比较运算符。

__lt__(self, other) __le__(self, other) __eq__(self, other) __ne__(self, other) __gt__(self, other) __ge__(self, other) 

must be provided individually. This can be abbreviated by using functools.total_ordering.

必须单独提供。可以通过使用functions . total_ordered对其进行缩写。

This however turns out rather unreadable and unpractical most of the time. Still you have to put similar code pieces in 2 funcs - or use a further helper func.

然而,这在大多数时候都是难以读懂和不切实际的。仍然需要将类似的代码片段放入两个函数中——或者使用一个进一步的helper函数。

So mostly I prefer to use the mixin class PY3__cmp__ shown below. This reestablishes the single __cmp__ method framework, which was and is quite clear and practical in most cases. One can still override selected rich comparisons.

因此,我更喜欢使用下面显示的mixin类PY3__cmp__。这重新建立了单一的__cmp__方法框架,这在大多数情况下是非常清晰和实用的。仍然可以覆盖选择的丰富比较。

Your example would just become:

你的例子会变成:

 class point(PY3__cmp__):      ...       # unchanged code

The PY3__cmp__ mixin class:

PY3 = sys.version_info[0] >= 3if PY3:    def cmp(a, b):        return (a > b) - (a < b)    # mixin class for Python3 supporting __cmp__    class PY3__cmp__:           def __eq__(self, other):            return self.__cmp__(other) == 0        def __ne__(self, other):            return self.__cmp__(other) != 0        def __gt__(self, other):            return self.__cmp__(other) > 0        def __lt__(self, other):            return self.__cmp__(other) < 0        def __ge__(self, other):            return self.__cmp__(other) >= 0        def __le__(self, other):            return self.__cmp__(other) <= 0else:    class PY3__cmp__:        pass