Cela dépend entièrement de l'objet i
.
+=
appelle la __iadd__
méthode (si elle existe - se replie __add__
si elle n'existe pas) alors qu'elle +
appelle la __add__
méthode 1 ou la __radd__
méthode dans quelques cas 2 .
Du point de vue de l'API, __iadd__
est censé être utilisé pour modifier les objets mutables en place (renvoyer l'objet qui a été muté) alors qu'il __add__
devrait renvoyer une nouvelle instance de quelque chose. Pour les objets immuables , les deux méthodes renvoient une nouvelle instance, mais __iadd__
placent la nouvelle instance dans l'espace de noms actuel avec le même nom que l'ancienne instance. C'est pourquoi
i = 1
i += 1
semble augmenter i
. En réalité, vous obtenez un nouvel entier et l'assignez "au-dessus de" i
- perdant une référence à l'ancien entier. Dans ce cas, i += 1
est exactement le même que i = i + 1
. Mais, avec la plupart des objets mutables, c'est une autre histoire:
À titre d'exemple concret:
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]
par rapport à:
a = [1, 2, 3]
b = a
b = b + [1, 2, 3]
print a #[1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
Remarquez comment dans le premier exemple, depuis b
et a
référence le même objet, quand je l' utilise +=
sur b
, il change réellement b
(et a
voit ce changement trop - Après tout, il est référence à la même liste). Dans le deuxième cas cependant, quand je le fais b = b + [1, 2, 3]
, cela prend la liste qui b
fait référence et la concatène avec une nouvelle liste [1, 2, 3]
. Il stocke ensuite la liste concaténée dans l'espace de noms actuel en tant que b
- Sans tenir compte de ce qu'était b
la ligne avant.
1 Dans l'expression x + y
, si x.__add__
n'est pas implémenté ou si x.__add__(y)
retourne NotImplemented
et x
et y
a différents types , x + y
essaie alors d'appeler y.__radd__(x)
. Donc, dans le cas où vous avez
foo_instance += bar_instance
si Foo
ne met pas en œuvre __add__
ou __iadd__
alors le résultat ici est le même que
foo_instance = bar_instance.__radd__(bar_instance, foo_instance)
2 Dans l'expression foo_instance + bar_instance
, bar_instance.__radd__
sera essayé avant foo_instance.__add__
si le type de bar_instance
est une sous-classe du type de foo_instance
(par exemple issubclass(Bar, Foo)
). La raison en est que, Bar
dans un certain sens, c'est un objet de "niveau supérieur" Foo
qui Bar
devrait donc avoir la possibilité de remplacer Foo
le comportement de.
+=
agit commeextend()
en cas de listes.