Each Answer to this Q is separated by one/two green lines.
I’m trying to create a Python script that opens several databases and compares their contents. In the process of creating that script, I’ve run into a problem in creating a list whose contents are objects that I’ve created.
I’ve simplified the program to its bare bones for this posting. First I create a new class, create a new instance of it, assign it an attribute and then write it to a list. Then I assign a new value to the instance and again write it to a list… and again and again…
Problem is, it’s always the same object so I’m really just changing the base object. When I read the list, I get a repeat of the same object over and over.
So how do you write objects to a list within a loop?
Here’s my simplified code
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
So how do I (append, extend, copy or whatever) the elements of simpleList so that each entry contains a different instance of the object instead of all pointing to the same one?
You demonstrate a fundamental misunderstanding.
You never created an instance of SimpleClass at all, because you didn’t call it.
for count in xrange(4): x = SimpleClass() x.attr = count simplelist.append(x)
Or, if you let the class take parameters, instead, you can use a list comprehension.
simplelist = [SimpleClass(count) for count in xrange(4)]
To fill a list with seperate instances of a class, you can use a for loop in the declaration of the list. The * multiply will link each copy to the same instance.
instancelist = [ MyClass() for i in range(29)]
and then access the instances through the index of the list.
instancelist.attr1 = 'whamma'
It shouldn’t be necessary to recreate the SimpleClass object each time, as some are suggesting, if you’re simply using it to output data based on its attributes. However, you’re not actually creating an instance of the class; you’re simply creating a reference to the class object itself. Therefore, you’re adding a reference to the same class attribute to the list (instead of instance attribute), over and over.
x = SimpleClass
x = SimpleClass()
Create a new instance each time, where each new instance has the correct state, rather than continually modifying the state of the same instance.
Alternately, store an explicitly-made copy of the object (using the hint at this page) at each step, rather than the original.
If I understand correctly your question, you ask a way to execute a deep copy of an object.
What about using copy.deepcopy?
import copy x = SimpleClass() for count in range(0,4): y = copy.deepcopy(x) (...) y.attr1= '*Bob* '* count
A deepcopy is a recursive copy of the entire object. For more reference, you can have a look at the python documentation: https://docs.python.org/2/library/copy.html
I think this simply demonstrates what you are trying to achieve:
# 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.number, l.name print l.number, l.name print Class.count, Class.names
Run the code above and you get:-
[<__main__.Class instance at 0x6311b2c>, <__main__.Class instance at 0x63117ec>] 0 uno 1 duo 2 ['uno', 'duo']