2012-04-07 51 views
5

the manual是說:最小方法在Python鴨打字訂購3.1

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

但我看到的錯誤:

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

當我運行這個測試:

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 

我很驚訝,當IntVar()在右邊,__int__()沒有被調用。我究竟做錯了什麼?

添加__gt__()修復了這個,而是指我不明白的最低要求是訂購...

感謝, 安德魯

+0

如果你看[豐富比較方法文檔](http://docs.python.org/release/3.1.3/reference/datamodel.html#object.__lt__),它特別提到了這種行爲 - 'There沒有這些方法的交換參數版本(當左邊的參數不支持這個操作,但是正確的參數的時候使用);相反,__lt __()和__gt __()是彼此的反射,__le __()和__ge __()是彼此的反射,__eq __()和__ne __()是他們自己的反射。 豐富的比較方法的參數從未被強制。# – agf 2012-04-07 13:45:17

+0

@agf:答案應該在答案中,而不是在評論中。 – 2012-04-07 15:56:36

+0

@EthanFurman雖然Sven的回答確實如此,但文檔並沒有引導你,而IMO則認爲這不僅僅是一個評論,而是一個回答。 – agf 2012-04-07 16:46:02

回答

4

Python 3.x都有永遠不會做任何運營商的強制類型轉換,因此__int__()未在此上下文中使用。比較

a < b 

都會先打電話type(a).__lt__(a, b),如果這個返回NotImplemented,它會調用type(b).__gt__(b, a)

來自文檔的引用是關於對單個類型進行比較,上面的解釋說明了爲什麼這對單個類型來說足夠了。

爲了使您的類型與int正確交互,您應該實現所有比較運算符,或使用Python 2.7或3.2中提供的total_ordering decorator

+0

謝謝。已經完全忘記了total_ordering。這將完美地完成。 – 2012-04-07 13:54:11

+1

total_ordering適用於您的情況。但是,使用total_ordering的兩個不同類可能會出錯:http://bugs.python.org/issue10042 – 2012-04-08 08:01:33