¿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):
...