I am new to python and trying to learn. Problem I am stuck at a place where I initialize and object of a class in the loop. During this initialization I expect that I get a brand new object with all its attribute reset. But that doesn't happen when for the array list the class has. Example below:
Class MyClass:
id=""
aList=[]
Class SecondClass: # ignore its content
pid=""
anObj=MyClass()
sc1=SecondClass()
anobj.append(sc1)
print str(len(anObj.aList) # gives the output 1
anObj=MyClass() # reinitalizing the object, so I expect on the lines of java that I get an empty class
print str(len(anObj.aList) # gives the output 1, why I just reinitialized the object "anObj"
What I want is after I do anObj=MyClass() all the attributes should be reset. Like java. It seems like anObj (array ) is treated as static variable of class (using Java language) Problem at deeper depth I don't want to do anObj.aList=[] explicitly because my issue is some thing like in the below code
aCollection=[]
for x in (0,3):
anObj=MyClass()
sc=getSecondClassObjectWithDifferentValues()
anobj.append(sc)
aCollection.append(anOb)
2 Answers 2
You are confusing static properties with instance property. You should be doing this instead:
Class MyClass:
def __init__(self):
self.id = ""
self.aList = []
The fundamental difference is that, in your implementation, the property aList will be the same for all instances of MyClass. This is why we call them static, because they do not change from instance to instance. In contrast, an instance variable defined as above will be unique for each new instance you create.
Comments
This is a super common misunderstanding with python ... effectively, MyClass.aList is a "static" member. The key to understanding this is to understand how python looks up attributes on an object.
First, python look at the instance for the attribute. If it isn't there, then python moves up a level (to the class) and looks for the attribute there. If it isn't on the class, it'll look at the base classes (in the "Method Resolution Order").
So, this (hopefully) explains the problem. you create an instance of MyClass and get a reference to it's list:
c = MyClass()
lst = c.aList
Now, note, c.aList is MyClass.aList because c doesn't have an aList attribute of it's own.
print(lst is MyClass.aList) # True
So, how do we resolve this? The typical fix for this is to bind the aList attribute to the instance at initialization time:
class MyClass(object):
def __init__(self):
self.aList = []
Now, MyClass doesn't have an aList member, but all of it's instances will (and their members will all be distinct).