Comportamiento de alcance desconcertante
-
29-10-2019 - |
Pregunta
Parece que no puedo entender lo que está pasando aquí:
class testclass:
def __init__(self):
print "new instance"
myList=[]
if __name__ == "__main__":
inst1=testclass()
inst1.myList.append("wrong")
inst2=testclass()
inst2.myList.append("behaviour")
print "I get the",inst2.myList
La salida es:
new instance
new instance
I get the ['wrong', 'behaviour']
Hubiera esperado que la lista en inst1 no sabe nada sobre la lista en inst2, pero de alguna manera parece el alcance de mi lista Trascends la instanciación de la clase. Encuentro esto muy inquietante y desconcertante, ¿o me estoy perdiendo algo aquí?
¡Gracias!
Solución
La forma en que definiste myList
es un atributo de clase.
El comportamiento que busca es el de un atributo de objeto:
class testclass:
def __init__(self):
print "new instance"
self.myList = []
Vamos a intentarlo:
>>> t1 = testclass()
new instance
>>> t2 = testclass()
new instance
>>> t1.myList.append(1)
>>> t2.myList.append(2)
>>> t1.myList
[1]
>>> t2.myList
[2]
Si está interesado en los atributos de clase, eche un vistazo a Documentación de clase. Dado que las clases en Python también son objetos, como (casi) todo en Python, pueden tener sus propios atributos.
Otros consejos
La forma en que declaraste myList
Dentro de la clase lo hace un clase atributo. Si tuviera la intención de tener un instancia atributo, declararlo así y tendrá el comportamiento esperado:
class testclass:
def __init__(self):
print "new instance"
self.myList=[]
Sí, porque para eso están los atributos de clase. Si desea una variable de instancia, debe declararlo en la instancia en sí, generalmente con self
dentro de un método.
myList
se inicializa en clase Tiempo de instancia, porque se declara en el cuerpo de la clase, no en objeto Tiempo de instancia.
Dichas propiedades se comparten con instancias, hasta que se crea una variable con el mismo nombre en la instancia.
Entonces, en su caso, está utilizando cada objeto para acceder a la misma myList
objeto (y agregarle un valor).
class testclass:
def __init__(self):
self.myList=[]
print "new instance"
Si desea que MyList sea una variable de instancia, debe definir a sí mismo. Mylist dentro de la función init. Entonces debes obtener el comportamiento que espera. Como lo tienes ahora, creo que MyList es una variable de clase, y será compartido por todas las instancias de la clase.