Como as pessoas nos comentários aqui e em duas outras perguntas marcadas como duplas parecem estar confusas sobre isso da mesma maneira, acho que vale a pena adicionar uma resposta adicional sobre a de Alex Coventry .
O fato de Alex estar atribuindo um valor de um tipo mutável, como uma lista, não tem nada a ver com o fato de as coisas serem compartilhadas ou não. Podemos ver isso com a id
função ou o is
operador:
>>> 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 você está se perguntando por que eu usei, em object()
vez de, digamos, 5
isso, é para evitar dois outros problemas que eu não quero abordar aqui; por duas razões diferentes, s totalmente criados separadamente 5
podem acabar sendo o mesma instância do número 5
. Mas s totalmente criados separadamente object()
não podem.)
Então, por que isso a.foo.append(5)
afeta no exemplo de Alex b.foo
, mas a.foo = 5
no meu exemplo não? Bem, tente a.foo = 5
no exemplo de Alex, e aviso de que ela não afeta b.foo
não quer .
a.foo = 5
está apenas criando a.foo
um nome para 5
. Isso não afeta b.foo
, ou qualquer outro nome para o valor antigo que a.foo
costumava se referir. * É um pouco complicado criar um atributo de instância que oculte um atributo de classe **, mas quando você obtém isso, nada é complicado. acontecendo aqui.
Espero que agora seja óbvio porque Alex usou uma lista: o fato de você poder alterar uma lista significa que é mais fácil mostrar que duas variáveis denominam a mesma lista e também significa que é mais importante no código da vida real saber se você tem duas listas ou dois nomes para a mesma lista.
* A confusão para pessoas provenientes de uma linguagem como C ++ é que, no Python, os valores não são armazenados em variáveis. Os valores residem em áreas de valor, por si só, variáveis são apenas nomes de valores e a atribuição apenas cria um novo nome para um valor. Se ajudar, pense em cada variável Python como uma em shared_ptr<T>
vez de a T
.
** Algumas pessoas aproveitam isso usando um atributo de classe como um "valor padrão" para um atributo de instância que as instâncias podem ou não definir. Isso pode ser útil em alguns casos, mas também pode ser confuso, portanto, tenha cuidado com isso.