以下代码
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))
在Python 2中运行良好,但在Python 3中我收到错误:
>>> p=point(2,3)
>>> q=point(3,4)
>>> p>q
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: point() > point()
它仅适用于==
和!=
。
答案 0 :(得分:48)
您需要在Python 3中提供丰富的排序比较方法,即__lt__
,__gt__
,__le__
,__ge__
,__eq__
和__ne__
。另见:PEP 207 -- Rich Comparisons。
__cmp__
没有更长时间使用。
更具体地说,__lt__
将self
和other
作为参数,并且需要返回self
是否小于other
。例如:
class Point(object):
...
def __lt__(self, other):
return ((self.x < other.x) and (self.y < other.y))
(这不是一个合理的比较实现,但很难说出你想要的是什么。)
因此,如果您遇到以下情况:
p1 = Point(1, 2)
p2 = Point(3, 4)
p1 < p2
这相当于:
p1.__lt__(p2)
将返回True
。
__eq__
将返回True
,否则返回False
。其他方法类似。
如果您使用functools.total_ordering
装饰器,则只需执行例如__lt__
和__eq__
方法:
from functools import total_ordering
@total_ordering
class Point(object):
def __lt__(self, other):
...
def __eq__(self, other):
...
答案 1 :(得分:11)
这是Python 3中一项重大而深思熟虑的更改。有关详细信息,请参阅here。
- 当操作数没有有意义的自然时,排序比较运算符(
<
,<=
,>=
,>
)会引发TypeError
异常排序。因此,1 < ''
,0 > None
或len <= len
等表达式不再有效,例如None < None
提升TypeError
而不是返回False
。一个必然结果是,对异构列表进行排序不再有意义 - 所有元素必须相互比较。请注意,这不适用于==
和!=
运算符:不同无比类型的对象总是相互比较不相等。builtin.sorted()
和list.sort()
不再接受提供比较功能的cmp
参数。请改用key
参数。注:key
和reverse
参数现在是“仅限关键字”。cmp()
函数应视为已消失,并且不再支持__cmp__()
特殊方法。使用__lt__()
进行排序,__eq__()
使用__hash__()
,并根据需要进行其他丰富的比较。 (如果您确实需要cmp()
功能,则可以使用表达式(a > b) - (a < b)
作为cmp(a, b)
的等效项。)
答案 2 :(得分:7)
在Python3中有六个丰富的比较运算符
__lt__(self, other)
__le__(self, other)
__eq__(self, other)
__ne__(self, other)
__gt__(self, other)
__ge__(self, other)
必须单独提供。这可以通过使用functools.total_ordering
来缩写。
所以我更喜欢使用下面显示的mixin类PY3__cmp__
。这将重新建立单__cmp__
方法框架,在大多数情况下,该方法非常明确且实用。人们仍然可以覆盖选定的丰富比较。
你的例子就变成了:
class point(PY3__cmp__):
...
# unchanged code
PY3 = sys.version_info[0] >= 3
if 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) <= 0
else:
class PY3__cmp__:
pass