Da die Leute in den Kommentaren hier und in zwei anderen Fragen, die als Dups markiert sind, alle auf die gleiche Weise verwirrt zu sein scheinen, denke ich, dass es sich lohnt, zusätzlich zu Alex Coventrys eine zusätzliche Antwort hinzuzufügen .
Die Tatsache, dass Alex einen Wert eines veränderlichen Typs wie eine Liste zuweist, hat nichts damit zu tun, ob Dinge geteilt werden oder nicht. Wir können dies mit der idFunktion oder dem isOperator sehen:
>>> 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
(Wenn Sie sich fragen, warum ich object()anstelle von beispielsweise verwendet habe, 5um zu vermeiden, dass ich auf zwei ganz andere Probleme stoße, auf die ich hier nicht eingehen möchte. Aus zwei verschiedenen Gründen können vollständig separat erstellte 5s die sein gleiche Instanz der Nummer 5. Aber völlig separat erstellte object()s können nicht.)
Warum a.foo.append(5)wirkt sich das in Alex 'Beispiel aus b.foo, a.foo = 5in meinem Beispiel jedoch nicht? Nun, versuchen a.foo = 5in Alex Beispiel, und bemerkt , dass es nicht wirkt sich b.foodort entweder .
a.foo = 5macht nur a.fooeinen Namen für 5. Dies wirkt sich nicht auf b.fooeinen anderen Namen für den alten Wert aus, auf den a.foofrüher Bezug genommen wurde. * Es ist etwas schwierig, ein Instanzattribut zu erstellen, das ein Klassenattribut verbirgt. ** Sobald Sie das erhalten, ist nichts kompliziertes passiert hier.
Hoffentlich ist jetzt klar, warum Alex eine Liste verwendet hat: Die Tatsache, dass Sie eine Liste mutieren können, bedeutet, dass es einfacher ist zu zeigen, dass zwei Variablen dieselbe Liste benennen, und dass es im realen Code wichtiger ist, zu wissen, ob Sie zwei Listen haben oder zwei Namen für dieselbe Liste.
* Die Verwirrung für Leute, die aus einer Sprache wie C ++ kommen, ist, dass in Python Werte nicht in Variablen gespeichert werden. Werte leben im Werteland von sich aus, Variablen sind nur Namen für Werte, und die Zuweisung erstellt nur einen neuen Namen für einen Wert. Wenn es hilft, stellen Sie sich jede Python-Variable als eine shared_ptr<T>anstelle von a vor T.
** Einige Benutzer nutzen dies, indem sie ein Klassenattribut als "Standardwert" für ein Instanzattribut verwenden, das von Instanzen festgelegt werden kann oder nicht. Dies kann in einigen Fällen nützlich sein, kann aber auch verwirrend sein. Seien Sie also vorsichtig damit.