Reputation: 1150
I have come across a situation that I believe has revealed a gap in my understanding of how references work in Python.
Suppose that we have two classes:
class A:
def __init__(self):
self.x = [1,2,3]
def modify(self):
self.x.append(4)
def reset(self):
self.x = []
class B:
def __init__(self, x):
self._x = x
def say(self):
print self._x
a = A()
b = B(a.x)
b.say()
a.modify()
b.say()
a.reset()
b.say()
The output I expected was:
[1, 2, 3]
[1, 2, 3, 4]
[]
The output I got was:
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4]
It seems that when I called reset()
and set self.x
to a new list, the reference held by B
became independent and lived on, thereby becoming a copy instead of a reference. Is this a correct understanding?
Upvotes: 1
Views: 211
Reputation: 7603
In fact, it is not _x in B that became a copy but x in A that became another list.
Upvotes: 0
Reputation: 8021
When you are assigning a.x to [], you are not cleaning the array rather assign a new empty array to a.x while it's reference: b._x is kept intact. If you want to modify and array in place, in your case delete all of it's contents do this:
del a.x[:]
Upvotes: 3
Reputation: 601471
The reset()
method
def reset(self):
self.x = []
does not modify the object stored in self.x
-- it rather creates a new empty list, which is then stored in self.x
. The old list is not altered (and since it is still referenced by b._x
, it is also not garbage collected). To get the behaviour you are after, use
def reset(self):
del self.x[:]
to empty the existing list instead of creating a new one.
Upvotes: 10