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 += 1
ist 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 b
und a
das gleiche Objekt verweisen, wenn ich +=
auf b
, es ändert sich tatsächlich b
(und a
sieht , 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 b
die 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 b
Zeile.
1 In dem Ausdruck x + y
, wenn x.__add__
nicht implementiert ist oder wenn x.__add__(y)
Erträge NotImplemented
und x
und y
verschiedene Typen haben , dann x + y
versucht Anruf y.__radd__(x)
. Also, in dem Fall, wo Sie haben
foo_instance += bar_instance
Wenn Foo
nicht 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_instance
eine Unterklasse von der Art der ist foo_instance
(zB issubclass(Bar, Foo)
). Der Grund für dies ist , weil Bar
in einem gewissen Sinne ist ein „höhere Ebene“ Objekt als Foo
so Bar
sollte die Möglichkeit erhalten , zu überschreiben Foo
‚s Verhalten.
+=
verhält sich wieextend()
bei Listen.