Changing one list unexpectedly changes another, too

Question:

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?

Asked By: sodiumnitrate

||

Answers:

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?

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[:]
Answered By: stackattack

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)
Answered By: Erez Haim

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?

Answered By: kpie

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! 🙂

Answered By: Dhananjay
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.