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 += 1est 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 bet aréférence le même objet, quand je l' utilise +=sur b, il change réellement b(et avoit 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 bfait 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 bla ligne avant.
1 Dans l'expression x + y, si x.__add__n'est pas implémenté ou si x.__add__(y)retourne NotImplemented et xet ya différents types , x + yessaie alors d'appeler y.__radd__(x). Donc, dans le cas où vous avez
foo_instance += bar_instance
si Foone 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_instanceest une sous-classe du type de foo_instance(par exemple issubclass(Bar, Foo)). La raison en est que, Bardans un certain sens, c'est un objet de "niveau supérieur" Fooqui Bardevrait donc avoir la possibilité de remplacer Foole comportement de.
+=agit commeextend()en cas de listes.