I have written following class which does the following:
class abc:
def __init__(self):
self.Values = []
def add_code(self):
lastval = self.Values
print "self.Values , ", self.Values
print "lastval , ", lastval
lastval.append(1)
print "self.Values 1, ", self.Values
print "lastval 1 , ", lastval
lastval.append(2)
print "lastval 2 , ", lastval
print "self.Values 2 , ", self.Values
lastval.append(3)
print "lastval 3 , ", lastval
print "self.Values 3 , ", self.Values
lastval.append(4)
print "last val 4 ", lastval
print "self.Values 4 , ", self.Values
lastval = []
print "last value is emtpy now? , ", lastval
print "But the self.Values is not", self.Values
return lastval
When I run this code I see that the variable lastval
gets appended with the values and so does the self.Values
But when I initialize the lastval
with empty list, I still see self.Values
holds to the values. What could be the reason
Why would you think otherwise? At first, you assign lastval
to point to the same list as self.Values
, so mutations to one will be seen in the other. But when you do lastval = []
you simply rebind lastval
to a new list, you don't affect self.Values
at all.
After the __init__
method has run, we have two objects in memory:
#1 Instance of abc
#2 Array
They contain:
#1 Instance of abc
Values : Reference to #2
#2 Array
[ ]
Now we call add_code and it runs:
lastval = self.Values
print "self.Values , ", self.Values
print "lastval , ", lastval
At this point, both lastval and self.Values are references to object #2, the array. So we have:
#1 Instance of abc
Values : Reference to #2
#2 Array
[ ]
Local variables
self : Reference to #1
lastval : Reference to #2
Continuing...
lastval.append(1)
print "self.Values 1, ", self.Values
print "lastval 1 , ", lastval
The append
method modifies object #2. So now we have:
#1 Instance of abc
Values : Reference to #2
#2 Array
[ 1 ]
Local variables
self : Reference to #1
lastval : Reference to #2
This continues similarly...
lastval.append(2)
print "lastval 2 , ", lastval
print "self.Values 2 , ", self.Values
lastval.append(3)
print "lastval 3 , ", lastval
print "self.Values 3 , ", self.Values
lastval.append(4)
print "last val 4 ", lastval
print "self.Values 4 , ", self.Values
So now we have:
#1 Instance of abc
Values : Reference to #2
#2 Array
[ 1, 2, 3, 4 ]
Local variables
self : Reference to #1
lastval : Reference to #2
At this point, we do something different:
lastval = []
This is an assignment to a local variable. It doesn't do anything to object #2. It creates a new array. So finally we have:
#1 Instance of abc
Values : Reference to #2
#2 Array
[ 1, 2, 3, 4 ]
#3 Array
[ ]
Local variables
self : Reference to #1
lastval : Reference to #3
As you can see, lastval and self.Values now refer to different objects.
The important thing to understand is the difference updating a variable to reference different objects, and mutating an existing object. For an in-depth discussion, see http://docs.python.org/3/reference/datamodel.html (That document is for Python 3, but there is no major difference in these concepts between Python 2 and Python 3.)
Classes have nothing (or not much) to do with this. The underlying effect is that several variables can hold the same list (this happens via assignment). And if you then change the list, all variables seem to change.
You might want to create copies of the lists to avoid that.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.