2

I was working with matrices in python, and after hours spent trying to debug a program, managed to trace the problem to essentially this code, where all non-zero entries of a matrix are uniformly increased.

list2=[[1,2],[0,4]]
list1=list2
for row in list1:
    for i in range(0,len(row)):
        if row[i]!=0:
            row[i]=row[i]+10
print(list1) #returns [[11,12],[0,14]], as expected
print(list2) #returns [[11,12],[0,14]], want to return [[1,2],[0,4]]

There's something fundamental I'm missing here. I thought by declaring list1=list2 a new list was created, which the rest of the code modified while keeping list2 unaltered.

What's the problem, and how do I fix it?

Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196
Cookie Monster
  • 147
  • 1
  • 6

2 Answers2

2

This code:

list2=[[1,2],[0,4]]
list1=list2

does not create a new list in list1, it simply binds the name list1 to the same object as list2. Therefore any changes made to the list via name list2 will also be visible via list1.

You could use the copy module:

import copy
list2 = [[1,2],[0,4]]
list1 = copy.deepcopy(list2)

list1 will now refer to a copy of list2 and changes to the list will be reflected only via list2.

For lists containing more complicated objects such as other lists, copy.deepcopy() will make recursive copies of the nested objects.

mhawke
  • 84,695
  • 9
  • 117
  • 138
2

The Problem; You are not copying the actual list

By doing list1 = list2 you are merely copying the handle to the list that list1 is referring to, in order to provide an actual copy you must say that this is what you want — explicitly.

Example

a = [1,2,3];
b = a
c = list(a) # create a new list, copying the elements in `a`
d = a[:]    # equivalent to `list(a)` (with a slightly weird syntax)
a[1] = 99
c[1] = 0
print (a) # [1,99,3]
print (b) # [1,99,3]
print (c) # [1,0,3]
print (d) # [1,2,3]

The Solution; Copying all the way down

The problem you are experienced will show up in an additional place since you have lists within a list. In order to make a deep copy all at once it is recommended to use copy.deepcopy, as in the below example.

import copy
list1 = copy.deepcopy (list2)

Documentation


Further reading

Community
  • 1
  • 1
Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196