32

I have a list of the form

v = [0,0,0,0,0,0,0,0,0]

Somewhere in the code I do

vec=v
vec[5]=5

and this changes both v and vec:

>>> print vec
[0, 0, 0, 0, 0, 5, 0, 0, 0]
>>> print v
[0, 0, 0, 0, 0, 5, 0, 0, 0]

Why does v change at all?

1
  • 1
    It is worth noting that this behaviour is is not limited to lists, it can also be observed with dict objects and would on tuple's too if they were mutable. Commented Apr 21, 2015 at 23:50

5 Answers 5

44

Why does v change at all?

vec and v are both references.

When coding vec = v you assign v address to vec. Therefore changing data in v will also "change" vec.

If you want to have two different arrays use:

vec = list(v)
Sign up to request clarification or add additional context in comments.

Comments

10

Because v is pointed to the same list as vec is in memory.

If you do not want to have that you have to make a

from copy import deepcopy
vec = deepcopy(v)

or

vec = v[:]

1 Comment

You don't need a deepcopy of a shallow list
5

Run this code and you will understand why variable v changes.

a = [7, 3, 4]
b = a
c = a[:]
b[0] = 10
print 'a: ', a, id(a)
print 'b: ', b, id(b)
print 'c: ', c, id(c)

This code prints the following output on my interpreter:

a:  [10, 3, 4] 140619073542552                                                                                                
b:  [10, 3, 4] 140619073542552                                                                                                
c:  [7, 3, 4] 140619073604136

As you can see, lists a and b point to the same memory location. Whereas, list c is a different memory location altogether. You can say that variables a and b are alias for the same list. Thus, any change done to either variable a or b will be reflected in the other list as well, but not on list c Hope this helps! :)

Comments

5

Python points both lists in vec = v to the same spot of memory.

To copy a list use vec = v[:]


This might all seem counter-intuitive. Why not make copying the list the default behavior? Consider the situation

def foo():
    my_list = some_function()
    # Do stuff with my_list

Wouldn't you want my_list to contain the exact same list that was created in some_function and not have the computer spend extra time creating a copy. For large lists copying the data can take some time. Because of this reason, Python does not copy a list upon assignment.



Misc Notes:

  • If you're familiar with languages that use pointers. Internally, in the resulting assembly language, vec and v are just pointers that reference the address in memory where the list starts.

  • Other languages have been able to overcome the obstacles I mentioned through the use of copy on write which allows objects to share memory until they are modified. Unfortunately, Python never implemented this.

  • For other ways of copying a list, or to do a deep copy, see List changes unexpectedly after assignment. Why is this and how can I prevent it?

Comments

1

you could use

vec=v[:] #but

"Alex Martelli's opinion (at least back in 2007) about this is, that it is a weird syntax and it does not make sense to use it ever. ;) (In his opinion, the next one is more readable)."

vec=list(v)

I mean it was Erez's link... "How to clone or copy a list in Python?"

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.