Python copy a list of lists [duplicate]

From the docs for the copy module:

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):

  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

When you call regular copy.copy() you are performing a shallow copy. This means that in a case of a list-of-lists, you will get a new copy of the outer list, but it will contain the original inner lists as its elements. Instead you should use copy.deepcopy(), which will create a new copy of both the outer and inner lists.

The reason that you didn't notice this with your first example of using copy([1,2]) is that the primitives like int are immutable, and thus it is impossible to change their value without creating a new instance. If the contents of the list had instead been mutable objects (like lists, or any user-defined object with mutable members), any mutation of those objects would have been seen in both copies of the list.


Perhaps a list comprehension as such:

new_list = [x[:] for x in old_list]

...though if your matrices are deeper than one layer, list comprehension is probably less elegant than just using deepcopy.

edit - a shallow copy, as stated, will still contain references to the objects inside the list. So for example...

>>> this = [1, 2]
>>> that = [33, 44]
>>> stuff = [this, that]
>>> other = stuff[:]
>>> other
[[1, 2], [33, 44]]
>>> other[0][0] = False
>>> stuff
[[False, 2], [33, 44]]    #the same problem as before
>>> this
[False, 2]                #original list also changed
>>> other = [x[:] for x in stuff]
>>> other
[[False, 2], [33, 44]]
>>> other[0][0] = True
>>> other
[[True, 2], [33, 44]]
>>> stuff
[[False, 2], [33, 44]]    #copied matrix is different
>>> this
[False, 2]                #original was unchanged by this assignment