2012-04-07 16 views
5

W the manual to mówi:Minimalne Sposoby zamawiania z kaczka wpisywanie w Pythonie 3.1

in general, __lt__() and __eq__() are sufficient, if you want the conventional meanings of the comparison operators

Ale widzę błąd:

>  assert 2 < three 
E  TypeError: unorderable types: int() < IntVar() 

kiedy uruchomić ten test:

from unittest import TestCase 

class IntVar(object): 

    def __init__(self, value=None): 
     if value is not None: value = int(value) 
     self.value = value 

    def __int__(self): 
     return self.value 

    def __lt__(self, other): 
     return self.value < other 

    def __eq__(self, other): 
     return self.value == other 

    def __hash__(self): 
     return hash(self.value) 

class DynamicTest(TestCase): 

    def test_lt(self): 
     three = IntVar(3) 
     assert three < 4 
     assert 2 < three 
     assert 3 == three 

Jestem zaskoczony, że kiedy IntVar() jest po prawej stronie, __int__() nie jest wywoływany. Co ja robię źle?

Dodawanie __gt__() poprawki, ale oznacza, że ​​nie rozumieją, co minimalne wymagania są do zamawiania ...

Dzięki, Andrew

+0

Jeśli spojrzysz na [bogatą metodę porównawczą docs] (http://docs.python.org/release/3.1.3/reference/datamodel.html#object.__lt__), to w szczególności wspomina to zachowanie: 'There nie są wymienionymi wersjami tych metod (do użycia, gdy lewy argument nie obsługuje operacji, ale właściwy argument ma taką wartość); raczej __lt __() i __gt __() są wzajemnymi odbiciami, __le __() i __ge __() są odbiciem siebie nawzajem, a __eq __() i __ne __() są ich własnym odbiciem. Argumenty do bogatych metod porównania nigdy nie są wymuszane. " – agf

+0

@agf: Odpowiedzi powinny być w odpowiedziach, a nie w komentarzach. –

+0

@EthanFurman Dokumenty nie chodzą po tobie, jak w konkretnym przypadku, takim jak odpowiedź Svena, i IMO, które są niezbędne, aby zasługiwać na publikację jako odpowiedź, a nie tylko na komentarz. – agf

Odpowiedz

4

Python 3.x nie zrobi żadnych coercions typu dla operatorów , więc __int__() nie jest używane w tym kontekście. Porównanie

a < b 

najpierw spróbuje zadzwonić type(a).__lt__(a, b), a jeśli to zwraca NotImplemented, to zadzwoń type(b).__gt__(b, a).

Cytat z dokumentacji dotyczy wykonywania porównań dla jednego typu, a powyższe wyjaśnienie pokazuje, dlaczego wystarczyłoby to dla jednego typu.

Aby twój typ współdziałał poprawnie z int, powinieneś zaimplementować cały operator porównania lub użyć total_ordering decorator dostępnego w Pythonie 2.7 lub 3.2.

+0

dzięki. całkowicie zapomniałem o total_ordering. to będzie doskonale. –

+1

total_ordering działa w twoim przypadku. Jednak dwie różne klasy, które używają total_ordering, mogą powodować błędy: http://bugs.python.org/issue10042 –