0

Say I have a vector a defined as:

a = [[1,2,3],[-1,-2,-3]]

I have learned that to create a copy of the object a without referencing it I should use the following syntaxis:

b = a[:]

Indeed, if I execute the following statements:

b = []
print a

the output is

>>> [[1,2,3],[-1,-2,-3]]

exactly as I was expecting. Though, if I do the following:

b = a[:]
b[0][2] = 'change a'
print a

the output is

>>> [[1,2,'change a'],[-1,-2,-3]]

So it's clear to me that the object a[0] is being referenced even if contained in a. How can I create a copy of the object a in a way that even all its internal objects will not be referenced?

Matteo NNZ
  • 11,930
  • 12
  • 52
  • 89

4 Answers4

5

a[:] creates a shallow copy of the list.

You can use the copy.deepcopy() function to recursively copy the objects, or use a list comprehension:

b = [el[:] for el in a]

This creates a new list object with shallow copies of the nested list objects in a.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
4

For that use deepcopy:

>>> from copy import deepcopy
>>> b = deepcopy(a)

>>> b[0][2] = 'change a'
>>> print a
[[1,2,3],[-1,-2,-3]]

Deepcopy: https://docs.python.org/2/library/copy.html#copy.deepcopy

Extension

Deepcopy also creates an individual copy of class instances. Please see simple example below.

from copy import deepcopy

class A:
    def __init__(self):
        self.val = 'A'

>>> a = A()
>>> b = deepcopy(a)

>>> b.val = 'B'
>>> print a.val
'A'
>>> print b.val
'B'
Community
  • 1
  • 1
sshashank124
  • 31,495
  • 9
  • 67
  • 76
4

Use copy.deepcopy

import copy
b = copy.deepcopy(a)

Quoting the docs:

A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original

Example:

>>> a = list(range(1000))
>>> b = copy.deepcopy(a)
>>> a is b    # b is a new object
False
>>> 
vaultah
  • 44,105
  • 12
  • 114
  • 143
4

If you only "shallow copy" b = a[:], each sub-list b[n] is still a reference to the same sub-list referenced at a[n]. Instead you need to do a deep(er) copy, e.g. by

b = [l[:] for l in a]

This creates a shallow copy of each sub-list, but as their contents are immutable that isn't a problem. If you have more levels of container nesting, you need copy.deepcopy as the other answers suggest.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437