Die allgemeine Antwort lautet, dass +=versucht wird, die __iadd__spezielle Methode aufzurufen , und wenn diese nicht verfügbar ist, wird versucht, sie zu verwenden__add__ stattdessen . Das Problem ist also der Unterschied zwischen diesen speziellen Methoden.
Die __iadd__spezielle Methode ist für eine In-Place-Addition vorgesehen, dh sie mutiert das Objekt, auf das sie einwirkt. Die __add__spezielle Methode gibt ein neues Objekt zurück und wird auch für den Standardoperator verwendet +.
Wenn der +=Operator für ein Objekt verwendet wird, für das eine __iadd__Definition vorliegt, wird das Objekt an Ort und Stelle geändert. Andernfalls wird stattdessen versucht, die Ebene zu verwenden __add__und ein neues Objekt zurückzugeben.
Aus diesem Grund +=ändert für veränderbare Typen wie Listen der Wert des Objekts, während für unveränderliche Typen wie Tupel, Zeichenfolgen und Ganzzahlen stattdessen ein neues Objekt zurückgegeben wird ( a += bentsprichta = a + b ).
Für die Typen , dass die Unterstützung sowohl __iadd__und __add__Sie deshalb sein müssen aufpassen , welche Sie verwenden. a += bruft auf __iadd__und mutiert a, während a = a + bein neues Objekt erstellt und zugewiesen wird a. Sie sind nicht die gleiche Operation!
>>> a1 = a2 = [1, 2]
>>> b1 = b2 = [1, 2]
>>> a1 += [3] # Uses __iadd__, modifies a1 in-place
>>> b1 = b1 + [3] # Uses __add__, creates new list, assigns it to b1
>>> a2
[1, 2, 3] # a1 and a2 are still the same list
>>> b2
[1, 2] # whereas only b1 was changed
Für unveränderliche Typen (wo Sie keine haben __iadd__) a += bund a = a + bgleichwertig sind. Dies ist es, was Sie +=für unveränderliche Typen verwenden können, was eine seltsame Entwurfsentscheidung sein könnte, bis Sie bedenken, dass Sie es sonst nicht +=für unveränderliche Typen wie Zahlen verwenden könnten !