Dado que las personas en los comentarios aquí y en otras dos preguntas marcadas como dups parecen estar confundidas acerca de esto de la misma manera, creo que vale la pena agregar una respuesta adicional además de la de Alex Coventry .
El hecho de que Alex asigne un valor de tipo mutable, como una lista, no tiene nada que ver con si las cosas se comparten o no. Podemos ver esto con la id
función o el 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
(Si se pregunta por qué lo usé en object()
lugar de, por ejemplo, 5
eso es para evitar toparme con otros dos problemas que no quiero abordar aquí; por dos razones diferentes, los correos electrónicos creados por separado 5
pueden terminar siendo misma instancia del número, 5
pero object()
no se pueden crear s completamente por separado ).
Entonces, ¿por qué a.foo.append(5)
en el ejemplo de Alex afecta b.foo
, pero a.foo = 5
en mi ejemplo no afecta? Bueno, trate a.foo = 5
en el ejemplo de Alex, y el aviso de que no afecta b.foo
existe tampoco .
a.foo = 5
solo se está convirtiendo a.foo
en un nombre para 5
. Eso no afecta b.foo
, ni ningún otro nombre para el valor anterior al que a.foo
solía referirse. * Es un poco complicado que estemos creando un atributo de instancia que oculte un atributo de clase, ** pero una vez que lo obtienes, nada complicado es sucediendo aquí
Con suerte, ahora es obvio por qué Alex usó una lista: el hecho de que pueda mutar una lista significa que es más fácil mostrar que dos variables nombran la misma lista, y también significa que es más importante en el código de la vida real saber si tiene dos listas o no. Dos nombres para la misma lista.
* La confusión para las personas que provienen de un lenguaje como C ++ es que en Python, los valores no se almacenan en variables. Los valores viven en tierra de valor, por sí solos, las variables son solo nombres para valores, y la asignación solo crea un nuevo nombre para un valor. Si ayuda, piense en cada variable de Python como en shared_ptr<T>
lugar de a T
.
** Algunas personas aprovechan esto usando un atributo de clase como un "valor predeterminado" para un atributo de instancia que las instancias pueden o no establecer. Esto puede ser útil en algunos casos, pero también puede ser confuso, así que tenga cuidado con eso.