2016-01-16 65 views
5

我有一個載體類方法:更改爲__add__,__mul__等操作的順序在自定義類

class Vector: 
    def __init__(self, x, y): 
     self.x, self.y = x, y 
    def __str__(self): 
     return '(%s,%s)' % (self.x, self.y) 
    def __add__(self, n): 
     if isinstance(n, (int, long, float)): 
      return Vector(self.x+n, self.y+n) 
     elif isinstance(n, Vector): 
      return Vector(self.x+n.x, self.y+n.y) 

的正常工作,也就是我可以這樣寫:

a = Vector(1,2) 
print(a + 1) # prints (2,3) 

然而如果操作的順序是相反的,那麼它失敗:

a = Vector(1,2) 
print(1 + a) # raises TypeError: unsupported operand type(s) 
      #     for +: 'int' and 'instance' 

我理解錯誤:增加一個int objec的t到Vector對象未定義,因爲我沒有在int類中定義它。有沒有辦法解決這個問題,而無需在int(或int的父級)類中定義它?

+0

好問題,你有我的upvote。 – plamut

+0

你可能會覺得這有幫助:[特殊方法名稱](https://docs.python.org/3/reference/datamodel.html#special-method-names)。另請參閱Rafe Kettler的[Python的魔術方法指南](http://www.rafekettler.com/magicmethods.html)和[Python的神奇方法](https://pythonconquerstheuniverse.wordpress.com/2012/03/ 09/pythons-magic-methods) –

回答

5

您還需要定義__radd__

有些操作不一定評估這樣的A + B = = B + A,這就是爲什麼Python的定義添加RADD方法。

更好地解釋我自己:它支持「int」沒有定義+操作和class Vector實例作爲操作的一部分。因此vector + 1與1 + vector不同。

當Python試圖查看1.__add__方法可以做什麼時,會引發異常。然後Python會去尋找Vector.__radd__操作來嘗試完成它。

在OP的情況評價爲__radd__ = __add__

class Vector(object): 

    def __init__(self, x, y): 
     self.x, self.y = x, y 

    def __str__(self): 
     return '(%s,%s)' % (self.x, self.y) 

    def __add__(self, n): 
     if isinstance(n, (int, long, float)): 
      return Vector(self.x+n, self.y+n) 
     elif isinstance(n, Vector): 
      return Vector(self.x+n.x, self.y+n.y) 

    __radd__ = __add__ 


a = Vector(1, 2) 
print(1 + a) 

,輸出足夠:

(2,3) 

這同樣適用於所有像數的操作。

+0

也許這裏需要更多的解釋嗎? –

+0

'__mul__','__div__'等類似嗎?所以'__rmul__','__rdiv__'等? – nluigi

+0

是的,如果操作中的第一個對象(一切都是對象)不支持第二個對象 – mementum

4

當你說x + y時,Python調用x.__add__(y)。如果x不執行__add__(或該方法返回NotImplemented),則Python會嘗試調用y.__radd__(x)作爲回退。

因此,您所要做的就是在Vector類中定義__radd__()方法,1 + y將按照您的預期工作。

注意:您也必須爲其他操作做類似操作,例如,執行__mul__()__rmul__()對等。

您可能還想看看this question,它更詳細地解釋了相同的原理。

更新: 根據你的使用情況,您可能還需要實現__iadd__()方法(和它的表兄弟)覆蓋+=操作。

例如,如果你說y += 1y是的Vector這裏的實例),你可能要修改y實例本身,而不是返回一個新Vector實例作爲一個結果,你的__add__()方法目前一樣。

+0

thx的答案和鏈接到問題! – nluigi

+0

我很樂意幫忙! – plamut