Dal momento che le persone nei commenti qui e in altre due domande contrassegnate come duplicate sembrano essere confuse su questo allo stesso modo, penso che valga la pena aggiungere una risposta aggiuntiva a quella di Alex Coventry .
Il fatto che Alex stia assegnando un valore di tipo mutabile, come un elenco, non ha nulla a che fare con il fatto che le cose siano condivise o meno. Possiamo vederlo con la id
funzione o l' is
operatore:
>>> 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
(Se ti stai chiedendo perché ho usato object()
invece, diciamo, 5
per evitare di imbattermi in altri due problemi che non voglio entrare qui; per due motivi diversi, i messaggi creati completamente separatamente 5
possono finire per essere il stessa istanza del numero 5
. Ma object()
non è possibile crearli interamente creati separatamente .)
Quindi, perché a.foo.append(5)
nell'esempio di Alex influisce b.foo
, ma a.foo = 5
nel mio esempio no? Bene, prova a.foo = 5
nell'esempio di Alex e nota che non influisce neancheb.foo
lì .
a.foo = 5
sta solo diventando a.foo
un nome per 5
. Ciò non influisce b.foo
, o qualsiasi altro nome per il vecchio valore a.foo
a cui si riferiva. * È un po 'complicato creare un attributo di istanza che nasconda un attributo di classe, ** ma una volta ottenuto ciò, nulla di complicato è sta succedendo qui.
Spero che ora sia ovvio il motivo per cui Alex ha usato un elenco: il fatto che puoi mutare un elenco significa che è più facile mostrare che due variabili nominano lo stesso elenco, e anche che è più importante nel codice della vita reale sapere se hai due elenchi o due nomi per lo stesso elenco.
* La confusione per le persone che provengono da un linguaggio come C ++ è che in Python i valori non sono memorizzati in variabili. I valori vivono nella terra dei valori, da soli, le variabili sono solo nomi per valori e l'assegnazione crea semplicemente un nuovo nome per un valore. Se aiuta, pensa a ciascuna variabile Python come a shared_ptr<T>
anziché a T
.
** Alcune persone ne traggono vantaggio utilizzando un attributo di classe come "valore predefinito" per un attributo di istanza che le istanze possono o meno impostare. Questo può essere utile in alcuni casi, ma può anche essere fonte di confusione, quindi fai attenzione.