Dies hängt ganz vom Objekt ab i.
+=ruft die __iadd__Methode auf (falls vorhanden) - __add__greift zurück, wenn sie nicht vorhanden ist), während +die __add__Methode 1 oder __radd__in einigen Fällen die Methode 2 aufgerufen wird .
Aus API-Sicht __iadd__soll es verwendet werden, um veränderbare Objekte an Ort und Stelle zu ändern (das mutierte Objekt zurückzugeben), während __add__eine neue Instanz von etwas zurückgegeben werden soll. Bei unveränderlichen Objekten geben beide Methoden eine neue Instanz zurück, __iadd__setzen die neue Instanz jedoch in den aktuellen Namespace mit demselben Namen wie die alte Instanz. Deshalb
i = 1
i += 1
scheint zu erhöhen i. In Wirklichkeit erhalten Sie eine neue Ganzzahl und weisen sie "über" zu i- wobei ein Verweis auf die alte Ganzzahl verloren geht. In diesem Fall i += 1ist genau das gleiche wie i = i + 1. Bei den meisten veränderlichen Objekten ist dies jedoch eine andere Geschichte:
Als konkretes Beispiel:
a = [1, 2, 3]
b = a
b += [1, 2, 3]
print a #[1, 2, 3, 1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
verglichen mit:
a = [1, 2, 3]
b = a
b = b + [1, 2, 3]
print a #[1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
Beachten Sie, wie im ersten Beispiel, da bund adas gleiche Objekt verweisen, wenn ich +=auf b, es ändert sich tatsächlich b(und asieht , dass der Wandel zu - Schließlich ist es die gleiche Liste ist Referenzierung). Im zweiten Fall b = b + [1, 2, 3]nimmt dies jedoch die Liste, auf bdie verwiesen wird, und verkettet sie mit einer neuen Liste [1, 2, 3]. Anschließend wird die verkettete Liste im aktuellen Namespace wie folgt gespeichert: b- Ohne Rücksicht auf die vorherige bZeile.
1 In dem Ausdruck x + y, wenn x.__add__nicht implementiert ist oder wenn x.__add__(y)Erträge NotImplemented und xund yverschiedene Typen haben , dann x + yversucht Anruf y.__radd__(x). Also, in dem Fall, wo Sie haben
foo_instance += bar_instance
Wenn Foonicht implementiert __add__oder __iadd__dann ist das Ergebnis hier das gleiche wie
foo_instance = bar_instance.__radd__(bar_instance, foo_instance)
2 In dem Ausdruck foo_instance + bar_instance, bar_instance.__radd__wird versucht werden , bevor , foo_instance.__add__ wenn die Art des bar_instanceeine Unterklasse von der Art der ist foo_instance(zB issubclass(Bar, Foo)). Der Grund für dies ist , weil Barin einem gewissen Sinne ist ein „höhere Ebene“ Objekt als Fooso Barsollte die Möglichkeit erhalten , zu überschreiben Foo‚s Verhalten.
+=verhält sich wieextend()bei Listen.