2017-08-09 81 views
0

我想了解操作符重寫如何爲自定義類的兩個操作數工作。在Python中重寫對於相同類操作數的交換操作

舉例來說,假設我有以下幾點:

class Adder: 
    def __init__(self, value=1): 
     self.data = value 
    def __add__(self,other): 
     print('using __add__()') 
     return self.data + other 
    def __radd__(self,other): 
     print('using __radd__()') 
     return other + self.data 

我初始化以下變量:

x = Adder(5) 
y = Adder(4) 

,然後繼續執行以下操作:

1 + x 
using __radd__() 
Out[108]: 6 

x + 2 
using __add__() 
Out[109]: 7 

的以上兩個操作似乎很直接。如果我的自定義類的成員位於添加表達式中的「+」的右側,則使用__radd__。如果它在左側,則使用__add__。這適用於表達式,其中一個操作數的類型爲Adder,另一個操作數是其他。

當我做到這一點,但是,我得到以下結果:

x + y 
using __add__() 
using __radd__() 
Out[110]: 9 

正如你可以看到,如果兩個操作數是自定義類的,那麼這兩個__add____radd__被調用。

我的問題是Python如何解開這種情況,它如何能夠調用右手加法函數以及左手加法函數。

+0

這是我的理解是'5 + y'應該叫回答'y .__ RADD __(5)'? – MadPhysicist

回答

1

這是因爲在您的方法中,您將數據添加到other。這本身就是Adder的一個實例。所以邏輯如下:

  • 在x上調用__add__;
  • 添加x.data(一個int)至y(加法器實例)
  • 啊,右邊的操作數是與__radd__方法一個實例,因此
  • Y上呼叫__radd__;
  • 將int加到y.data(另一個int)。

一般你會檢查,看看是否other是你的類的實例,如果是添加other.data而不僅僅是other

1

這是因爲您的__add____radd__方法的實施並沒有對Adder類的實例給予任何特殊處理。因此,每個__add__調用導致整數加上加法器實例操作,由於右側的加法器實例,進一步需要__radd__

您可以通過執行解決此問題:

def __add__(self, other): 
    print('using __add__()') 
    if isinstance(other, Adder): 
     other = other.data 
    return self.data + other 

def __radd__(self, other): 
    print('using __radd__()') 
    return self.__add__(other) 
+0

這是有道理的。你是說當Python遇到右側的「Adder」實例而不是一個整數時,那麼它會使它成爲一個整數? – MadPhysicist

+0

@MadPhysicist不會稱之爲[魔術](https://xkcd.com/628/)。你會如何期望在第一個'x .__ add __(y)'調用之後解析'5 + y'? –

+0

這是我感到困惑的部分。你怎樣才能輸入'__add__'並從它返回而不需要爲'a + b'類型的表達式得到完整的答案? '__add__'分析第一個操作數並確定它是'x = 5',然後將結果'5 + y'反彈到'__radd__'方法? – MadPhysicist