小編一直都覺本身公衆號的排版很雞肋,從這篇文章開始將使用了新的排版風格,還特地地作了一個卡通二維碼(見文末),但願你們會喜歡(不要臉地僞裝有不少粉絲)。其實關於排版,小編要真心感謝一下景禹大佬的指導。好了,今天想跟你們談談如何重載運算符+,認真看完這篇文章,你將收穫:python
你們都知道若a和b都是同類型序列,a+b能夠實現序列接拼,若a和b都是int或者float等數值類型,a+b會實現數學上的加法,見示例1。spa
#示例1 a = (1,2) b = (4,5) print(a+b) #(1,2,4,5) a = [1,2] b = [4,5] print(a+b) #[1,2,4,5] a = b = 1 print(a+b) #2 a = b = 1.0 print(a+b) #2.0
可是,若是a和b是不一樣類型的序列,他們可否接拼成功呢?code
要回答這個問題,咱們先了解一下Python爲中綴運算符特殊方法提供的特殊分派機制,其流程見下圖。component
對於表達式a+b,爲了支持涉及不一樣類型的運算,Python解釋器會執行如下幾步操做。blog
radd 是 __ add __的「反向」版本,Alex、Anna和Leo幾位技術大佬喜歡稱之爲「右向」(right)特殊方法,由於他們都在右操做數上調用。ip
若是a和b是不一樣類型的序列,執行示例2的程序,會發生什麼呢?rem
#示例2 a = (1,2) b = [3,4] print(a+b)
首先解釋器會調用a.__ add (b)方法,由於a和b是不一樣類型的序列,因此返回NotImplemented。而後解釋器檢查b是否有b. radd __ (a) 方法,而後調用該方法,可是仍是返回NotImplemented,最終拋出TypeError結果。數學
TypeError: can only concatenate tuple (not "list") to tuple
關於重載運算符,有幾點須要注意一下的:it
如今咱們嘗試定義一個Vector類,見示例3。class
#示例3 class Vector(object): def __init__(self,components): self.components = list(components)
若是咱們不對Vector重載運算符+,兩個Vector類相加拋出錯誤,見示例4
#示例4 v1 = Vector([1,2,3]) v2 = Vector([1,2,3]) print(v1+v2) #TypeError: unsupported operand type(s) for +: 'Vector' and 'Vector'
好了,咱們如今立刻對Vector重載運算符+吧,見示例5,可是咱們不是實現接拼,而是實現數學上的加法,由於對於一個向量,接拼功能意義不大。
#示例5 class Vector(object): def __init__(self,components): self.components = list(components) def __iter__(self): return iter(self.components) def __str__(self): return str(self.components) def __add__(self,others): print("__add__") try: pairs = itertools.zip_longest(self,others,fillvalue=0.0) return Vector(a+b for a,b in pairs) except TypeError: return NotImplemented v1 = Vector([1,2,3]) v2 = Vector([1,2,3]) v3 = [1,2,3] print(v1+v2) print(v1+v3)
輸出結果:
__add__ [2,4,6] __add__ [2,4,6]
從示例5中能夠看到,解析器調用了__ add __方法實現了兩個Vector或者Vector和具備數值元素的可迭代類型的相加。示例5可以實現V1+V3,那是否能實現V3+v1呢?見示例6。
#示例6 print(V3+V1) #TypeError: can only concatenate list (not "Vector") to list
示例6拋出錯誤了,當解釋器執行v3.__ add (V1)時候,由於調用的是列表的 add 方法,不能與自定義的類型相加,因此返回結果NotImplemented,並嘗試執行V1. radd (V3)方法,可是在自定義的Vector類並無實現該方法,因此最後仍是拋出了TypeError。好了,如今嘗試實現Vector類的 radd __ 方法。在示例5的基礎上添加示例7的代碼。
#示例7 def __radd__(self,other): print("__radd__") return self+other
再次運行示例6,獲得以下輸出結果。
__radd__ __add__ [2, 4, 6]
當解釋器執行V3.__ add (V1)返回NotImplemented以後,就會調用自定義類中的 radd 方法, radd 方法把計算結果委託給 add __ ,事實上,任何可交換的運算符均可以這麼作。
好啦,以上就是就是小編今天分享的內容,但願對你有用。
公衆號:CVpython
專一於分享Python和計算機視覺,快點掃碼關注我吧!