Changing one list unexpectedly changes another, too

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?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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)

Method 2

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

Method 3

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?

Method 4

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

Method 5

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?


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x