2012-04-07 10 views
5

In the manual è dice:Metodi minimi per l'ordinazione con duck typing in Python 3.1

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

Ma vedo l'errore:

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

quando ho eseguito questo 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 

Sono sorpreso che quando IntVar() è sulla destra, __int__() non viene chiamato. Che cosa sto facendo di sbagliato?

Aggiunta __gt__() consente la correzione, ma significa non capisco quali sono i requisiti minimi sono per ordinare ...

Grazie, Andrew

+0

Se si guardano i [metodi di confronto dei metodi di conversione] (http://docs.python.org/release/3.1.3/reference/datamodel.html#object.__lt__), si cita espressamente questo comportamento - 'Là non ci sono versioni degli argomenti scambiati di questi metodi (da utilizzare quando l'argomento di sinistra non supporta l'operazione ma l'argomento di destra lo fa); piuttosto, __lt __() e __gt __() sono il riflesso dell'altro, __le __() e __ge __() sono il riflesso reciproco, e __eq __() e __ne __() sono il loro riflesso. Gli argomenti per i metodi di confronto non sono mai forzati. – agf

+0

@agf: le risposte devono essere in Risposte, non nei commenti. –

+0

@EthanFurman I documenti non ti accompagnano nonostante il caso specifico come la risposta di Sven, e IMO che è necessario per meritare la pubblicazione come risposta, non solo un commento. – agf

risposta

4

Python 3.x non potrà mai fare qualsiasi tipo coercizioni per gli operatori , quindi __int__() non viene utilizzato in questo contesto. Il confronto

a < b 

in primo luogo provare a chiamare type(a).__lt__(a, b), e se questo ritorna NotImplemented, si chiamerà type(b).__gt__(b, a).

La citazione dalla documentazione riguarda il fatto che i confronti funzionano per un singolo tipo e la spiegazione sopra mostra perché questo sarebbe sufficiente per un singolo tipo.

Per fare in modo che il tuo tipo interagisca correttamente con int, è necessario implementare tutto l'operatore di confronto oppure utilizzare lo total_ordering decorator disponibile in Python 2.7 o 3.2.

+0

grazie. aveva completamente dimenticato di total_ordering. quello farà perfettamente. –

+1

opera nel tuo caso total_ordering. Tuttavia, due diverse classi che utilizzano sia total_ordering possono segnalare bug: http://bugs.python.org/issue10042 –

Problemi correlati