python python-3.x python-2.x partial-ordering

¿Por qué no puedo usar el método__cmp__ en Python 3 como para Python 2?



python set() function (3)

La siguiente pieza de código

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))

funciona bien en Python 2, pero en Python 3 me sale un error:

>>> 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()

Solo funciona para == y != .


En Python3 los seis operadores de comparación ricos

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

debe ser proporcionado de forma individual. Esto se puede abreviar mediante el uso de functools.total_ordering .

Sin embargo, esto resulta bastante ilegible y poco práctico la mayor parte del tiempo. Todavía tienes que poner pedazos de código similares en 2 funcs, o usar un func adicional.

Así que sobre todo prefiero usar la clase mixin PY3__cmp__ muestra a continuación. Esto restablece el único marco de trabajo __cmp__ , que fue y es bastante claro y práctico en la mayoría de los casos. Todavía se puede anular las comparaciones enriquecidas seleccionadas.

Tu ejemplo simplemente se convertiría en:

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

La clase 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


Este fue un cambio importante y deliberado en Python 3. Consulte here para obtener más detalles.


__lt__ proporcionar los métodos de comparación ricos para ordenar en Python 3, que son __lt__ , __gt__ , __le__ , __ge__ , __eq__ , y __ne__ . Ver también: PEP 207 - Comparaciones ricas .

__cmp__ ya no se usa.

Más específicamente, __lt__ toma al self y al other como argumentos, y necesita devolver si el self es menos que el other . Por ejemplo:

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

(Esta no es una implementación de comparación sensata, pero es difícil decir para qué se estaba buscando).

Entonces, si tienes la siguiente situación:

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

Esto será equivalente a:

p1.__lt__(p2)

que regresaría True .

__eq__ devolvería True si los puntos son iguales y False contrario. Los otros métodos funcionan análogamente.

Si usa el decorador functools.total_ordering , solo necesita implementar, por ejemplo, los métodos __lt__ y __eq__ :

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