Bien que beaucoup de temps a passé et beaucoup de choses correctes ont été dit, il n'y a pas de réponse qui bundles ces deux effets.
Vous avez 2 effets:
- un "spécial", peut-être inaperçu comportement de listes avec
+=
(comme l'a déclaré Scott Griffiths)
- le fait que les attributs de classe ainsi que des attributs d'instance sont impliqués (tel que déclaré par Peut Berk Büder)
Dans la classe foo
, __init__
méthode permet de modifier l'attribut de classe. C'est parce qu' self.bar += [x]
se traduit par self.bar = self.bar.__iadd__([x])
. __iadd__()
est pour en place les modifications, donc il modifie la liste et retourne une référence à elle.
Notez que l'instance dict est modifié, bien que ce ne serait normalement pas nécessaire que la classe dict contient déjà la même affectation. Si ce détail passe presque inaperçu - sauf si vous faites un foo.bar = []
par la suite. Ici, les instances de l' bar
reste la même, grâce à la dit fait.
Dans la classe foo2
, cependant, la classe bar
est utilisé, mais pas touché. Au lieu de cela, un [x]
est ajouté, formant un nouvel objet, comme self.bar.__add__([x])
qui est appelé ici, ce qui ne veut pas modifier l'objet. Le résultat est mis dans l'instance dict ensuite, en donnant l'exemple de la nouvelle liste des dict, tandis que la classe de l'attribut reste modifiés.
La distinction entre ... = ... + ...
et ... += ...
affecte aussi bien les missions par la suite:
f = foo(1) # adds 1 to the class's bar and assigns f.bar to this as well.
g = foo(2) # adds 2 to the class's bar and assigns g.bar to this as well.
# Here, foo.bar, f.bar and g.bar refer to the same object.
print f.bar # [1, 2]
print g.bar # [1, 2]
f.bar += [3] # adds 3 to this object
print f.bar # As these still refer to the same object,
print g.bar # the output is the same.
f.bar = f.bar + [4] # Construct a new list with the values of the old ones, 4 appended.
print f.bar # Print the new one
print g.bar # Print the old one.
f = foo2(1) # Here a new list is created on every call.
g = foo2(2)
print f.bar # So these all obly have one element.
print g.bar
Vous pouvez le vérifier l'identité des objets avec print id(foo), id(f), id(g)
(n'oubliez pas le supplémentaires ()
s si vous êtes sur Python3).
BTW: L' +=
opérateur est appelé "augmentée" d'assignation et d'une façon générale, vise à faire en place des modifications aussi loin que possible.