LeS LeS - 1 month ago 18
Python Question

Modifying a clone of a list (python)

I have 2 lists :

l1 = [[1,2,3],[4,5,6],[7,8,9]]
l2 = list(l1)


According to this post if I modify
l2
,
l1
should not change.

But if I do the following:

del l2[1][1]


l1
will be modified as well.

Is this intended and how can I prevent it from happening?
I also noticed that the ids of
l1[1]
and
l2[1]
are the same.

Answer

list(l1) will make a shallow copy of l1; that is, all references inside the list l1 will be copied to the new list. Modifications to these nested lists will be visible in the original list since you modify objects with the same reference.

Take a look at the matching ids for the lists:

print("l1 object references: ", *map(id, l1))
l1 object references:  139927285488584 139927284661256 139927284723784

print("l2 object references: ", *map(id, l2))
l2 object references:  139927285488584 139927284661256 139927284723784

If you didn't have lists in lists, this wouldn't be an issue:

l1 = [1,2,3]
l2 = list(l1)    
del l2[1]    
print(l1)  # [1, 2, 3]
print(l2)  # [1, 3]

The solution is, instead of using list, use copy.deepcopy:

import copy

l1 = [[1,2,3],[4,5,6],[7,8,9]]
l2 = copy.deepcopy(l1)
del l2[1][1]
print(l1)  # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Now the ids of the nested lists are different and mutating one leaves the other alone:

print("l1 object references: ", *map(id, l1))
l1 object references:  139927284726984 139927284737160 139927284737800

print("l2 object references: ", *map(id, l2))
l2 object references:  139927284710216 139927285123976 139927284678344

Of course, a list comprehension where list is called on every element also suffices in achieving the same effect :-)