Because python passes lists by reference
This means that when you write "b=a" you're saying that a and b are the same object, and that when you change b you change also a, and viceversa
A way to copy a list by value:
new_list = old_list[:]
If the list contains objects and you want to copy them as well, use generic copy.deepcopy():
import copy
new_list = copy.deepcopy(old_list)
Answer from Nikaido on Stack OverflowBecause python passes lists by reference
This means that when you write "b=a" you're saying that a and b are the same object, and that when you change b you change also a, and viceversa
A way to copy a list by value:
new_list = old_list[:]
If the list contains objects and you want to copy them as well, use generic copy.deepcopy():
import copy
new_list = copy.deepcopy(old_list)
Since Python passes list by reference, A and B are the same objects. When you modify B you are also modifying A. This behavior can be demonstrated in a simple example:
>>> A = [1, 2, 3]
>>> def change(l):
... b = l
... b.append(4)
...
>>> A
[1, 2, 3]
>>> change(A)
>>> A
[1, 2, 3, 4]
>>>
If you need a copy of A use slice notation:
B = A[:]
python list by value not by reference - Stack Overflow
python - How do I clone a list so that it doesn't change unexpectedly after assignment? - Stack Overflow
How do I copy a list without replacing the original one?
Why is copying a list so damn difficult in python?
You cannot pass anything by value in Python. If you want to make a copy of a, you can do so explicitly, as described in the official Python FAQ:
b = a[:]
To copy a list you can use list(a) or a[:]. In both cases a new object is created.
These two methods, however, have limitations with collections of mutable objects as inner objects keep their references intact:
>>> a = [[1,2],[3],[4]]
>>> b = a[:]
>>> c = list(a)
>>> c[0].append(9)
>>> a
[[1, 2, 9], [3], [4]]
>>> c
[[1, 2, 9], [3], [4]]
>>> b
[[1, 2, 9], [3], [4]]
>>>
If you want a full copy of your objects you need copy.deepcopy
>>> from copy import deepcopy
>>> a = [[1,2],[3],[4]]
>>> b = a[:]
>>> c = deepcopy(a)
>>> c[0].append(9)
>>> a
[[1, 2], [3], [4]]
>>> b
[[1, 2], [3], [4]]
>>> c
[[1, 2, 9], [3], [4]]
>>>
Hey r/learnpython
I am having trouble copying a list from an imported script I made without changing the original list. I tried to use this code:
def spawn_npcs():
for npc in SETTINGS.levels_list[SETTINGS.current_level].npcs:
try:
stats = [x for x in SETTINGS.npc_types if x[0]['id'] == npc[2]][0].copy()
print(stats[0]['pos'], SETTINGS.npc_types[0][0]['pos'])
stats[0]['pos'] = npc[0]
except:
print("ERROR: No NPC with ID = ", npc[2])
print(stats[0]['pos'], SETTINGS.npc_types[0][0]['pos'])It prints [0,0] [0,0] to the console and then [4,4] [4,4]. It also changed the list in SETTINGS.py - How do I avoid that?
Thanks :-)
I am sure there is a reason for this design in Python but why is it so difficult to clone a list? Copying a variable is easy
foo = 1 bar = foo bar = 2 print bar # returns 2 print foo # returns 1
But trying to do the same thing, which is what makes sense in my mind coming from other languages, does not work. You have to add the list splice otherwise it doesn't work.
Then I spent a day trying to figure out how to copy a 2d list and that was even more frustrating. I had the following code and none of these worked to properly copy a list without modifying the original.
foo = [[1,2], [3,4], [5,6]]
bar = foo # doesnt work
bar = foo[:] # doesnt work
bar = list(foo) # doesnt work
bar = list(foo[:]) # doesnt work
bar = []
bar += foo # doesnt work
bar = []
bar.append(foo) # doesnt work
for i, x in enumerate(foo):
bar[i] = x[:]
# didnt workI am sure I tried a few more methods and none of them worked. It was finally this method that was the only way I could find to copy a 2d list, modify the new one without affecting the original list
bar = [x[:] for x in foo]
So why is copying a list in python just so hard?