2012-08-07 70 views
5

完成以下代碼的最自然的方法是什麼?如何在實現比較運算符時處理混合類型?

import functools 

@functools.total_ordering 
class X: 
    def __init__(self, a): 
     self._a = a 

    def __eq__(self, other): 
     if not isinstance(other, X): 
      return False 
     return self._a == other._a 

    def __lt__(self, other): 
     if not isinstance(other, X): 
      return ...     // what should go here? 
     return self._a < other._a 

if __name__ == '__main__': 
    s = [2, 'foo', X(2)] 
    s.sort() 
    print s 

回答

2

你可以選擇任何感覺自然的東西; False表示你的實例總是按照其他類型排序,True,它們將在之前被排序。

或者,您也可以返回NotImplemented(見the __lt__ and other comparison methods documentation)信號不支持比較:

def __lt__(self, other): 
    if not isinstance(other, X): 
     return NotImplemented 
    return self._a < other._a 

引用文檔:

豐富的比較方法,如果它返回的單NotImplemented沒有爲給定的一對參數實現操作。按照慣例,返回FalseTrue以成功比較。但是,這些方法可以返回任何值,因此如果在布爾上下文中使用比較運算符(例如,在if語句的條件下),Python將調用bool()來確定結果是true還是false。

+1

只是返回False或True不是一個好主意。考慮這種情況,當你有另一個類似的類Y並且做X('foo') X('foo')。結果可能不一致。 – user763305 2012-08-07 12:24:35

+1

但是返回NotImplemented不起作用。然後,Python將使用自己的默認排序,這有點武斷,但一致。 – user763305 2012-08-07 12:25:37

4

我個人的做法:

例外。

不同類型之間沒有自然順序。

官方之一:(選擇這一項,應該有)

雖然我不同意這種說法完全手冊明確指出它是如何要做到:

http://docs.python.org/library/stdtypes.html#comparisons

不同類型的對象,除了不同的數字類型和 不同的字符串類型,永遠不會比較相等;這樣的對象被一致但是任意地排列爲 (以便排序異構陣列 產生一致的結果)。此外,某些類型(例如, 文件對象)僅支持簡單的比較概念,其中任何類型的兩個對象都不相等。同樣,這些對象被任意但一致地訂購 。當任何操作數是一個複數時,<,< =,>和> =運算符將引發TypeError異常 。

所以基本上......我會提出一個例外,但是排序的最pythonic方式是遵守手冊。

應該有一個 - 最好只有一個 - 明顯的方法來做到這一點。

+0

但是Python確實執行了這樣的命令。我可以對列表進行排序[2.3,'foo',int]。 – user763305 2012-08-07 12:07:15

+0

'1''一個字符串'是假的,'1''一個字符串'是真的。 – 2012-08-07 12:08:00

+0

具體而言,'TypeError(「無法與{}格式(type(self),type(other)))進行比較。 – ecatmur 2012-08-07 12:09:09