1

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?

3 Answers 3

10

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.

Sign up to request clarification or add additional context in comments.

1 Comment

another way is to use a @property decorator to access x.
3

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[:]

Comments

0

In fact, it is not _x in B that became a copy but x in A that became another list.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.