Puisque les personnes dans les commentaires ici et dans deux autres questions marquées comme dups semblent toutes 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 de type mutable, comme une liste, n'a rien à voir avec le fait que les choses soient partagées ou non. Nous pouvons le voir avec la id
fonction ou l' is
opérateur:
>>> 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é object()
au lieu de, disons, 5
c'est pour éviter de rencontrer deux autres problèmes que je ne veux pas aborder ici; pour deux raisons différentes, des s entièrement créés séparément 5
peuvent finir par être le même instance du nombre 5
. Mais les object()
s 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 pas a.foo = 5
dans mon exemple? Eh bien, essayez a.foo = 5
l'exemple d'Alex et notez que cela n'affecte pas b.foo
là non plus .
a.foo = 5
fait juste a.foo
un nom pour 5
. Cela n'affecte pas b.foo
, ou tout autre nom pour l'ancienne valeur qui 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 obtenez cela, rien de compliqué n'est se passe ici.
Espérons que la raison pour laquelle Alex a utilisé une liste est maintenant évidente: le fait que vous puissiez muter une liste signifie qu'il est plus facile de montrer que deux variables nomment la même liste, et signifie également 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 qu'en Python, les valeurs ne sont pas stockées dans des variables. Les valeurs vivent seules dans le domaine des valeurs, les variables ne sont que des noms de valeurs et l'affectation crée simplement un nouveau nom pour une valeur. Si cela vous aide, considérez chaque variable Python comme un shared_ptr<T>
fichier au lieu d'un T
.
** Certaines personnes en profitent en utilisant un attribut de classe comme "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 prêter à confusion, alors faites attention.