Étant donné que les personnes qui commentent ici et dans deux autres questions marquées comme dupliquées semblent toutes être confuses à ce sujet de la même manière, je pense qu'il vaut la peine d'ajouter une réponse supplémentaire en plus de celle d'Alex Coventry.
Le fait qu'Alex attribue une valeur d'un type mutable, comme une liste, n'a rien à voir avec le fait que les choses sont partagées ou non. Nous pouvons le voir avec la fonction id
ou l'opérateur is
:
>>> class A: foo = object()
>>> a, b = A(), A()
>>> a.foo is b.foo
True
>>> class A:
... def __init__(self): self.foo = object()
>>> a, b = A(), A()
>>> a.foo is b.foo
False
(Si vous vous demandez pourquoi j'ai utilisé <code>object()</code> au lieu, disons, de <code>5</code>, c'est pour éviter de rencontrer deux autres problèmes dont je ne veux pas parler ici; pour deux raisons différentes, des <code>5</code> créés entièrement séparément peuvent finir par être la même instance du nombre <code>5</code>. Mais des <code>object()</code> créés entièrement séparément ne le peuvent pas.)
Alors, pourquoi est-ce que a.foo.append(5)
dans l'exemple d'Alex affecte b.foo
, mais a.foo = 5
dans mon exemple ne le fait pas? Eh bien, essayez a.foo = 5
dans l'exemple d'Alex, et remarquez que cela n'affecte pas non plus b.foo
là-bas.
a.foo = 5
fait simplement de a.foo
un nom pour 5
. Cela n'affecte pas b.foo
, ni tout autre nom pour l'ancienne valeur à laquelle a.foo
faisait référence.* C'est un peu délicat que nous créons un attribut d'instance qui cache un attribut de classe,** mais une fois que vous avez compris cela, rien de compliqué ne se passe ici.
En espérant que maintenant il est évident pourquoi Alex a utilisé une liste: le fait que vous pouvez muter une liste signifie qu'il est plus facile de montrer que deux variables nomment la même liste, et cela signifie aussi qu'il est plus important dans le code réel de savoir si vous avez deux listes ou deux noms pour la même liste.
* La confusion pour les personnes venant d'un langage comme C++ est que en Python, les valeurs ne sont pas stockées dans des variables. Les valeurs vivent dans le monde des valeurs, par elles-mêmes, les variables ne sont que des noms pour des valeurs, et l'assignation crée simplement un nouveau nom pour une valeur. Si cela aide, pensez à chaque variable Python comme à un <code>shared_ptr<t></t></code> au lieu d'un <code>T</code>.
** Certaines personnes en profitent en utilisant un attribut de classe comme une "valeur par défaut" pour un attribut d'instance que les instances peuvent ou non définir. Cela peut être utile dans certains cas, mais cela peut aussi être source de confusion, alors soyez prudent avec cela.
1 votes
Je viens de réaliser qu'une question similaire a été posée et répondue ici: stackoverflow.com/questions/206734/… Dois-je supprimer cette question?
3 votes
C'est votre question, n'hésitez pas à la supprimer. Puisque c'est la vôtre, pourquoi demander l'opinion de quelqu'un d'autre?