Почему я не могу использовать метод __cmp__ в Python 3 как для Python 2?

Следующий fragment кода

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 "", line 1, in  TypeError: unorderable types: point() > point() 

Он работает только для == и != .

Вам необходимо предоставить богатые методы сравнения для заказа в 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 .

Это, однако, получается довольно непроницаемым и непрактичным в большинстве случаев. Тем не менее, вы должны поместить похожие fragmentы кода в 2 funcs – или использовать дополнительную вспомогательную функцию.

Поэтому в основном я предпочитаю использовать class mixin PY3__cmp__ показанный ниже. Это восстанавливает единственную __cmp__ метода __cmp__ , которая была и остается довольно ясной и практичной в большинстве случаев. Все еще можно переопределить выбранные богатые сравнения.

Ваш пример просто станет:

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

Класс mix: PY3__cmp__:

 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 
Interesting Posts

Как очистить пароль безопасности BIOS на этом ноутбуке?

jQuery изменение цвета цветной пользовательский прокрутка

Обнаружение doubleclick в строке TableView JavaFX

Интерфейсы C #. Неявная реализация по сравнению с явной реализацией

какими должны быть значения GOPATH и GOROOT?

Как предотвратить несколько экземпляров активности при запуске с различными намерениями

Как установить или изменить версию Java (JDK) по умолчанию на OS X?

Преобразование десятичной в двоичную Java

Как вы можете сделать безопасный статический синглтон в Rust?

Когда следует использовать ugettext_lazy?

Вызов метода Spring @Transaction методом одного и того же classа не работает?

Является ли «Безопасность доступа к коду» для любого реального мира?

Обозначение Postfix в дереве выражений

Как включить обработчики маршрута в несколько файлов в Express?

Как заменить экранный буфер vim предыдущей активностью bash после выхода?

Давайте будем гением компьютера.