2011-11-26 22 views
22

Cuando utilizo el código en Python 2 funciona bien, mientras que Python 3 me da el errorPython 2 y Python 3 __cmp__

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

............... .................................................. ...

[email protected]:~/Documents/Programs$ python3 -i classes.py 
>>> 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() 
>>> 
[email protected]:~/Documents/Programs$ python -i classes.py 
>>> p=point(2,3) 
>>> q=point(3,4) 
>>> p>q 
False 
>>> 

........................................ ...........................

En python 3 da un error en and mientras trabaja para solo == y !=.

Por favor, sugiera una solución.

Respuesta

29

Necesita proporcionar el método __lt__ y __eq__ para ordenar en Python 3. __cmp__ ya no se utiliza.

Actualizado a responder a preguntas/comentarios a continuación

__lt__ toma self y other como argumentos, y tiene que devolver si self es menor que other. Por ejemplo:

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

lo tanto, si usted tiene la siguiente situación:

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

p1 < p2 

Ésta será equivalente a:

p1.__lt__(p2) 

cual se devolvía True. __eq__ devolvería True si los puntos son iguales y False en caso contrario. Si utiliza el decorador functools.total_ordering como se recomienda a continuación, sólo tiene que proporcionar __lt__ y __eq__:

from functools import total_ordering 

@total_ordering 
class Point(object): 
    def __lt__(self, other): 
     ... 

    def __eq__(self, other): 
     ... 
+4

La recomendación PEP 8 es proporcionar a todos los seis comparaciones ricos. Para hacerlo más fácil, use * functools.total_ordering *. –

+1

¿cómo uso __lt y__eq__ en lugar de __cmp__? –

+0

Bueno, 'lt' significa Less Than. Devuelve un valor booleano que indica si 'self' es menor que el otro parámetro. Los otros funcionan de manera similar. Estoy seguro de que puedes descubrir los detalles. –

8

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

2

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) 

se debe proporcionar de forma individual. Esto puede abreviarse usando 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.

Por lo general, prefiero usar la clase mixin PY3__cmp__ que se muestra a continuación. Esto restablece el único marco de método __cmp__, que era 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 podría convertirse simplemente:

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

El PY3__cmp__ clase 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 
+0

Me gustó la forma en que escribiste los operadores. Sin embargo, explique esta afirmación (a> b) - (a theBuzzyCoder

+1

@theBuzzyCoder 'bool' es solo una subclase de' int', por lo que 'True' y' False' son básicamente 1 y 0, respectivamente. Dado que 'cmp' devuelve un valor negativo si su primer argumento es menor que su segundo argumento, cero si los argumentos son iguales, o un valor positivo de lo contrario, puede ver que' False - False == 0', 'True - False = = 1', y 'False - True == -1' proporcionan los valores de retorno correctos para' cmp'. – chepner

Cuestiones relacionadas