Creating a list of objects in Python

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):

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)

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

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[5].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.

Instead of:

x = SimpleClass

you need:

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:

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 = name
        Class.count += 1

print l
print l[0].number, l[0].name
print l[1].number, l[1].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']

The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .