2009-06-26 82 views
38

是否可以在Python中覆蓋+ =?在Python中重寫「+ =」? (__iadd __()方法)

+1

確切的重複http://stackoverflow.com/questions/728361/is-there-a-way-to-overload-in-python – 2009-12-29 09:29:35

+4

是的,但使用網站搜索:+ = python沒有給出結果。將報價放在「+ =」附近給出結果,但大多數情況下,報紙無法通過頭條新聞來判斷。儘管通過谷歌搜索發現這一點。 – 2010-12-26 21:10:01

回答

76

是的,覆蓋__iadd__方法。例如:

def __iadd__(self, other): 
    self.number += other.number 
    return self  
+30

如果您的類表示不可變對象,則不應該實現`__iadd__`。在這種情況下,只需實現`__add__`來代替`+ =`。例如,你可以在不可變的類型(如字符串和整數)上使用`+ =`,這是無法用`__iadd__`完成的。 – 2010-01-04 23:26:57

12

除了超載__iadd__(記得要回自己!),你也可以回退到上__add__,爲x + = Y會像X = X + Y。 (這是+ =運營商的陷阱之一。)

>>> class A(object): 
... def __init__(self, x): 
...  self.x = x 
... def __add__(self, other): 
...  return A(self.x + other.x) 
>>> a = A(42) 
>>> b = A(3) 
>>> print a.x, b.x 
42 3 
>>> old_id = id(a) 
>>> a += b 
>>> print a.x 
45 
>>> print old_id == id(a) 
False 

它甚至trips up experts

class Resource(object): 
    class_counter = 0 
    def __init__(self): 
    self.id = self.class_counter 
    self.class_counter += 1 

x = Resource() 
y = Resource() 

你期望x.idy.idResource.class_counter有什麼樣的價值觀?

9

除了什麼是正確答案上面給出的,這是值得澄清明確的是,當__iadd__被覆蓋,則x += y操作不__iadd__方法的結束而終止。

取而代之的是以x = x.__iadd__(y)結尾。換句話說,在實現完成後,Python會將您實現的實現的返回值分配給您要「添加到」的對象。

這意味着可以對x += y操作的左側進行變異,以便最終的隱式步驟失敗。考慮當你添加的東西的清單中這會發生什麼:現在

>>> x[1] += y # x has two items

,如果你的__iadd__實現(在x[1]對象的方法)錯誤地或故意刪除的第一項(x[0])從列表開始,Python將運行您的__iadd__方法)&嘗試將其返回值分配給x[1]。這將不再存在(將在x[0]),導致ÌndexError

或者,如果您__iadd__插入東西的上面的例子中x開始,你的目標將是在x[2],不x[1],不管是早些時候在x[0]現在將在x[1]和被分配__iadd__的返回值調用。

除非人們明白髮生了什麼,否則導致的錯誤可能是修復的噩夢。