2013-11-01 203 views
5

我遇到了一些令人困惑的魔法比較方法。 假設我們有下面的類:Python魔法混淆

class MutNum(object): 
    def __init__ (self, val): 
     self.val = val 

    def setVal(self, newval): 
     self.val = newval 

    def __str__(self): 
     return str(self.val) 

    def __repr__(self): 
     return str(self.val) 

    # methods for comparison with a regular int or float: 
    def __eq__(self, other): 
     return self.val == other 

    def __gt__(self, other): 
     return self.val > other 

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

    def __ge__(self, other): 
     return self.__gt__(other) or self.__eq__(other) 

    def __le__(self, other): 
     return self.__lt__(other) or self.__eq__(other) 

類做的事情是應該做的,一個MutNum對象比較正規的整數或浮點數是沒有問題的。然而,這是我不明白的地方,當魔法方法被給予兩個MutNum對象時,它甚至會比較好。

a = MutNum(42) 
b = MutNum(3) 
print(a > b) # True 
print(a >= b) # True 
print(a < b) # False 
print(a <= b) # False 
print(a == b) # False 

爲什麼這樣嗎?謝謝。

+1

例如,可能會認爲'__gt__'和'__lt__'與'__add__'和'__radd__'存在相同的關係。如果第一個不適用,Python會嘗試使用顛倒的操作數的另一個。 – chepner

回答

4

它計算如下(使用repr般的符號,而不是指變量):

MutNum(42) > MutNum(3) 
=> MutNum(42).__gt__(MutNum(3)) 
=> MutNum(42).val > MutNum(3) 
=> 42 > MutNum(3) 

從那裏,它只是你已經知道的作品INT-MutNum比較。

+0

@dust *你說*比較常規整數和浮點數與這個類的實例不是問題;-)'42> ...'不會再調用'MutNum .__ gt__',因爲42不是'MutNum'。這種混淆是沒有定義'__repr__'的原因之一,但添加了一些從它包裝的數字中提取'MutNum'的東西。 – delnan

2

如果你扔在一些打印和/或sys.stderr.write的,我想你會看到發生了什麼。 EG:

def __gt__(self, other): 
    sys.stderr.write('__gt__\n') 
    sys.stderr.write('{}\n'.format(type(other))) 
    sys.stderr.write('{} {}\n'.format(self.val, other)) 
    result = self.val > other 
    sys.stderr.write('result {}\n'.format(result)) 
    return result 

def __lt__(self, other): 
    sys.stderr.write('__lt__\n') 
    sys.stderr.write('{}\n'.format(type(other))) 
    sys.stderr.write('{} {}\n'.format(self.val, other)) 
    result = self.val < other 
    sys.stderr.write('result {}\n'.format(result)) 
    return result 

當您嘗試self.val(一個int)比其他(一MutNum),蟒蛇實現它沒有任何關係比較一個int到MutNum,並反轉比較的秩序,將MutNum與int進行比較 - 這是您定義的內容。也就是說,一個單獨的>比較正如您所期望的那樣執行>,但它也在執行<。