Почему я не могу использовать метод cmp в Python 3 как для Python 2?
следующий фрагмент кода
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()
это работает только для ==
и !=
.
3 ответов
вам нужно предоставить богатые методы сравнения для заказа в Python 3, которые являются __lt__
, __gt__
, __le__
, __ge__
, __eq__
и __ne__
. См. также: PEP 207 -- богатые сравнения.
__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):
...
Это было серьезное и преднамеренное изменение в Python 3. См.здесь для более подробной информации.
в Python3 шесть богатых операторов сравнения
__lt__(self, other)
__le__(self, other)
__eq__(self, other)
__ne__(self, other)
__gt__(self, other)
__ge__(self, other)
необходимо обеспечить индивидуально. Это можно сократить с помощью functools.total_ordering
.
это, однако, оказывается довольно нечитаемым и непрактичным большую часть времени. Тем не менее, вы должны поместить аналогичные фрагменты кода в 2 функции - или использовать дополнительный вспомогательный func.
поэтому в основном я предпочитаю использовать класс mixin PY3__cmp__
показано ниже. Это восстанавливает сингл __cmp__
метод framework, который был и есть довольно ясный и практичный в большинстве случаев. Все еще можно переопределить выбранные богатые сравнения.
ваш пример просто стало:
class point(PY3__cmp__):
...
# unchanged code
класс py3__cmp__ mixin:
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