2011-11-26 15 views
22

Kiedy użyć kodu w Pythonie 2 działa dobrze podczas Pythonie 3 to daje mi błądPython 2 i 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 
>>> 

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

W python 3 daje błąd na and, a działa tylko dla == i !=.

Proszę zaproponować rozwiązanie.

Odpowiedz

29

Musisz podać __lt__ i __eq__ metodę zamawiania w Pythonie 3. __cmp__ nie jest już używany.

Aktualizacja do odpowiedzi na pytania/komentarze poniżej

__lt__ trwa self i other jako argumenty i musi powrócić czy self jest mniejsza niż other. Na przykład:

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

Więc jeśli masz następującą sytuację:

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

p1 < p2 

to będzie równoważne:

p1.__lt__(p2) 

Które powrotu True. __eq__ powróci True, jeśli punkty są równe i False w przeciwnym razie. Jeśli używasz functools.total_ordering dekorator jak zalecono poniżej, trzeba tylko dostarczyć __lt__ i __eq__:

from functools import total_ordering 

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

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

PEP 8 zalecenie jest dostarczenie wszystkich sześciu bogatych porównań. Aby to ułatwić, użyj * functools.total_ordering *. –

+1

Jak używać __lt i__eq__ zamiast __cmp__? –

+0

Cóż, 'lt' oznacza mniej niż. Zwraca wartość logiczną wskazującą, czy 'self' jest mniejsze niż drugi parametr. Pozostałe działają podobnie. Jestem pewien, że potrafisz ustalić szczegóły. –

8

Była to poważna i przemyślana zmiana w Pythonie 3. Więcej informacji na ten temat można znaleźć na stronie here.

2

W Python3 sześć bogate operatory porównania

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

muszą być dostarczone indywidualnie. Można to skrócić za pomocą functools.total_ordering.

To jednak okazuje się raczej nieczytelne i niepraktyczne przez większość czasu. Nadal musisz umieścić podobne elementy w 2 funkcjach - lub skorzystać z dodatkowej funkcji helpera.

Tak więc najczęściej wolę korzystać z klasy mixin PY3__cmp__ pokazanej poniżej. Powoduje to ponowne ustanowienie pojedynczej struktury metody, która była i jest dość jasna i praktyczna w większości przypadków. Nadal można zastąpić wybrane porównania bogate.

Twój Przykładem może po prostu stać:

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

PY3__cmp__ mixin klasa:

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

Podobał mi się sposób, w jaki napisałeś operatorów. Proszę jednak wyjaśnić to stwierdzenie (a> b) - (a theBuzzyCoder

+1

@BuzzyCoder 'bool' to tylko podklasa' int', więc 'True' i' False' to odpowiednio 1 i 0. Ponieważ 'cmp' zwraca wartość ujemną, jeśli jej pierwszy argument jest mniejszy od drugiego argumentu, zero, jeśli argumenty są równe, lub wartość dodatnia inaczej, można zauważyć, że' False - False == 0', 'True - False = = 1' i 'False - True == -1' dostarczają poprawnych wartości zwracanych dla' cmp'. – chepner