Creando una lista de objetos en Python

Estoy intentando crear un script de Python que abre varias bases de datos y compara sus contenidos. En el proceso de crear ese script, me he encontrado con un problema al crear una lista cuyos contenidos son objetos que he creado.

He simplificado el progtwig para su publicación. Primero creo una nueva clase, creo una nueva instancia de ella, le asigno un atributo y luego lo escribo en una lista. Luego asigno un nuevo valor a la instancia y nuevamente lo escribo en una lista … y una y otra vez …

El problema es que siempre es el mismo objeto, así que solo estoy cambiando el objeto base. Cuando leo la lista, repito una y otra vez el mismo objeto.

Entonces, ¿cómo escribir objetos en una lista dentro de un bucle?

Aquí está mi código simplificado

class SimpleClass(object): pass x = SimpleClass # Then create an empty list simpleList = [] #Then loop through from 0 to 3 adding an attribute to the instance 'x' of SimpleClass for count in range(0,4): # each iteration creates a slightly different attribute value, and then prints it to # prove that step is working # but the problem is, I'm always updating a reference to 'x' and what I want to add to # simplelist is a new instance of x that contains the updated attribute x.attr1= '*Bob* '* count print "Loop Count: %s Attribute Value %s" % (count, x.attr1) simpleList.append(x) print '-'*20 # And here I print out each instance of the object stored in the list 'simpleList' # and the problem surfaces. Every element of 'simpleList' contains the same attribute value y = SimpleClass print "Reading the attributes from the objects in the list" for count in range(0,4): y = simpleList[count] print y.attr1 

Entonces, ¿cómo puedo (agregar, extender, copiar o lo que sea) los elementos de simpleList para que cada entrada contenga una instancia diferente del objeto en lugar de que todos apunten al mismo?

Demuestras un malentendido fundamental.

Nunca creaste una instancia de SimpleClass, porque no la llamaste.

 for count in xrange(4): x = SimpleClass() x.attr = count simplelist.append(x) 

O, si deja que la clase tome parámetros, en su lugar, puede usar una lista de comprensión.

 simplelist = [SimpleClass(count) for count in xrange(4)] 

Para llenar una lista con instancias separadas de una clase, puede usar un bucle for en la statement de la lista. La * multiplicación vinculará cada copia a la misma instancia.

 instancelist = [ MyClass() for i in range(29)] 

y luego acceder a las instancias a través del índice de la lista.

 instancelist[5].attr1 = 'whamma' 

No debería ser necesario volver a crear el objeto SimpleClass cada vez, como algunos sugieren, si simplemente lo está utilizando para generar datos en función de sus atributos. Sin embargo, en realidad no estás creando una instancia de la clase; simplemente estás creando una referencia al objeto de clase en sí. Por lo tanto, está agregando una referencia al mismo atributo de clase a la lista (en lugar del atributo de instancia), una y otra vez.

En lugar de:

 x = SimpleClass 

necesitas:

 x = SimpleClass() 

Cree una nueva instancia cada vez, donde cada nueva instancia tenga el estado correcto, en lugar de modificar continuamente el estado de la misma instancia.

Alternativamente, almacene una copia explícita del objeto (usando la sugerencia en esta página ) en cada paso, en lugar del original.

Si entiendo correctamente tu pregunta, pides una forma de ejecutar una copia profunda de un objeto. ¿Qué pasa con el uso de copy.deepcopy?

 import copy x = SimpleClass() for count in range(0,4): y = copy.deepcopy(x) (...) y.attr1= '*Bob* '* count 

Una copia profunda es una copia recursiva de todo el objeto. Para obtener más información, puede consultar la documentación de Python: https://docs.python.org/2/library/copy.html

Creo que esto simplemente demuestra lo que estás tratando de lograr:

 # coding: utf-8 class Class(): count = 0 names = [] def __init__(self,name): self.number = Class.count self.name = name Class.count += 1 Class.names.append(name) l=[] l.append(Class("uno")) l.append(Class("duo")) print l print l[0].number, l[0].name print l[1].number, l[1].name print Class.count, Class.names 

Ejecuta el código de arriba y obtienes: –

 [<__main__.Class instance at 0x6311b2c>, <__main__.Class instance at 0x63117ec>] 0 uno 1 duo 2 ['uno', 'duo']