Reputation: 363
I'm trying to make a list of objects in python. I'm doing this by making one object and appending it. Here is my code.
#Creating a Python object
class TestDat(object):
Dat1 = None
Dat2 = None
#Declaring the Test Array
TestArray = []
#Declaring the object
Test1 = TestDat()
#Defining the member variables in said object
Test1.Dat1 = 0
Test1.Dat1 = 1
#Appending the object to the List
TestArray.append(Test1)
#Rewriting and appending again
Test1.Dat1 = 3
Test1.Dat1 = 4
TestArray.append(Test1)
#Printing our Our Results
print TestArray[0].Dat1
print TestArray[1].Dat1
When I test it out. I get the output "4 4". This means that both elements of the list are the same. It seems like append is just copying a pointer to the object instead of a copy of said object. I would eventually like to do this in a loop so I can't be doing that. How can I get both elements of the List to be different without using a new object?
Upvotes: 4
Views: 111960
Reputation: 208
There are several mistakes here:
First, you have inherited from "object" and there is no need to explicitly put it, you can leave it empty.
Second, the way you declared your variables in your class makes the class share the same values across all instances, thats why you get the latest modified values always. you should use "self.variable" instead, and declare a constructor function for that.
Third, you are modifying Test1.Dat1 4 times and appending the same object twice. thats why you get the same object every time.
this is the right way:
class TestDat(): # leave this empty
def __init__(self): # constructor function using self
self.Dat1 = None # variable using self.
self.Dat2 = None # variable using self
TestArray = [] #empty array
Test1 = TestDat() #this is an object
Test2 = TestDat() #this is another object
Test1.Dat1 = 0 #assigning value to object 1
Test1.Dat2 = 1 #assigning value to object 1
Test2.Dat1 = 3 #assigning value to object 2
Test2.Dat2 = 4 #assigning value to object 2
TestArray.append(Test1) #append object 1
TestArray.append(Test2) #append object 2
print (TestArray[0].Dat1) # this is Test1
print (TestArray[1].Dat1) # this is Test2
or even simpler:
class TestDat():
def __init__(self, Dat1, Dat2):
self.Dat1 = Dat1
self.Dat2 = Dat2
TestArray = [TestDat(0,1),
TestDat(3,4)]
print (TestArray[0].Dat1) # this is Test1
print (TestArray[1].Dat1) # this is Test2
or this way:
class TestDat():
def __init__(self):
self.Dat1 = None
self.Dat2 = None
TestArray = [] #empty array
size = 2 #number of loops
for x in range(size): # appending empty objects
TestArray.append(TestDat())
#initialize later
TestArray[0].Dat1 = 0
TestArray[0].Dat2 = 1
TestArray[1].Dat1 = 3
TestArray[1].Dat2 = 4
print("print everithing")
for x in range(len(TestArray)):
print("object "+str(x))
print(TestArray[x].Dat1)
print(TestArray[x].Dat2)
Upvotes: 15
Reputation: 45243
I'm trying to make a list of objects in python. I'm doing this by making one object
You simply can't do this; your second statement contradicts your first statement. You must instantiate as many objects as you wish to have, end of story. Even if you try to use some kind of copy
function, it is just creating a new instance for you under the hood.
What you can do is use a for
loop to create your array.
testArray = []
for i in range(10):
testDat = TestDat(dat1=i, dat2=i*2)
testArray.append(testDat)
If you don't want to use a for
loop, you can just instantiate a new instance before appending it to the array.
testArray = []
testDat = TestDat(dat1=1, dat2=2)
testArray.append(testDat)
testDat = TestDat(dat1=3, dat2=4) # re-assigns the variable to the new instance
testArray.append(testDat)
If you have an existing list of items from which you are creating this array of objects, the best thing you can do is use a list comprehension to build your new list. For instance, if you had an array of tuples:
myOriginalData = [(1,2), (3,4), (5,6)]
myNewList = [TestDat(dat1=x, dat2=y) for (x,y) in myOriginalData]
Upvotes: 0
Reputation: 2442
You're right, when you add objects it does add them by reference.
There's a couple ways to do this. Probably the cleanest is just to make a new object for each entry. If you absolutely need to use the same instances with changed values, you can use copy.copy
:
from copy import copy
...
# Set up object
TestArray.append(copy(test1))
# Change stuff
TestArray.append(copy(test2))
See: https://docs.python.org/2/library/copy.html for the differences between copy
(aka shallow copy) and deepcopy
, as it may be important depending on the complexity of your object. It also tells you how to implement __copy__
and __deepcopy__
if copying the object is nontrivial.
So, TL;DR is I'd really suggest using new objects and discourage mutability, but copy
is there if you need it.
Upvotes: 0