2

I am having a bit of trouble with a python class I have created. I have tried to create the most simple class possible to debug it by stripping out any unrelated code. I still have the same issue.

class MyClass(object):

    def __init__(self):
        self.row = ['1', '2', '3', '4', '5', '6', '7', '8', '9']

    def get_row(self):
        return self.row

if __name__ == "__main__":
    a = MyClass()

    b = a.row

    b.remove('1')

    print(a.row)
    print(b)

The output is:

['2', '3', '4', '5', '6', '7', '8', '9']
['2', '3', '4', '5', '6', '7', '8', '9']

What is happening is when I do the b.remove('1') it removes the first entry from the b list as expected but when I look at a.row it has also been removed from it. My understanding of classes and return values it that b should have been a copy of a, it appears to behave more like a pointer in this case.

Any help in explaining how this has actually worked would be much appreciated.

1
  • I'm afraid your understanding is incorrect. All values are objects in python, and attributes and names are references to these objects. a.row is the reference to the list, you are merely making a copy of that reference, not the value itself. Commented Jan 10, 2014 at 13:52

2 Answers 2

5

From the Python documentation:

Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.

(source)

Basically, you'll need to explicitly make a new copy of a.row. You're right that it's behaving like a pointer.

List-specific example, with pictures:

Python doesn’t have variables like C. In C a variable is not just a name, it is a set of bits; a variable exists somewhere in memory. In Python variables are just tags attached to objects.

Consider the following statement:

a = [1, 2, 3]

It means that a points to the list [1, 2, 3] we just created, but a is not the list. If we do:

b = a

We didn't copy the list referenced by a. We just created a new tag b and attached it to the list pointed by a. Like in the picture below:


(source: precheur.org)

[ ... ]

Now we want to copy the list referenced by a. We need to create a new list to attach b to it.

(source)

Since a.row is a list, try this:

b = list(a.row)
Sign up to request clarification or add additional context in comments.

1 Comment

It's all about the difference between mutable/immutable data types in Python. Nice graphic.
1

As said by Milo Price, when you do b = a.row, b now stores a reference to a.row. So when you change b, it will also change a.row. You can also try slicing the list, ie, b = a.row[:]

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.