Python objects confusion: a=b, modify b and a changes! [duplicate]

Solution 1:

What you are experiencing is the concept of references. All objects in Python have a reference and when you assign one to two names a and b, this results in both a and b pointing to the same object.

>>> a = range(3)
>>> b = a                     # same object
>>> b.append(3)
>>> a, b                      # same contents
([0, 1, 2, 3], [0, 1, 2, 3])

With lists, you can make create a new list b that is a copy of another a using b = a[:].

>>> a = range(3)
>>> b = a[:]                  # make b a new copy of a
>>> b.append(3)
>>> a, b                      # a is left unchanged
([0, 1, 2], [0, 1, 2, 3])

For a more general solution for any object, use the copy module. A shallow copy will copy the references stored within the object you're copying, whereas a deep copy will recursively make new copies of all objects.

>>> a = [range(2), range(3)]
>>> b = copy.copy(a)          # shallow copy of a, equivalent to a[:]
>>> b[0] = range(4)
>>> a, b                      # setting an element of b leaves a unchanged
([[0, 1], [0, 1, 2]], [[0, 1, 2, 3], [0, 1, 2]])
>>> b[1].append(3)
>>> a, b                      # modifying an element of b modifies the element in a
([[0, 1], [0, 1, 2, 3]], [[0, 1, 2, 3], [0, 1, 2, 3]])

>>> a = [range(2), range(3)]
>>> b = copy.deepcopy(a)      # deep recursive copy of a
>>> b[1].append(3)
>>> a, b                      # modifying anything in b leaves a unchanged
([[0, 1], [0, 1, 2]], [[0, 1], [0, 1, 2, 3]])

Solution 2:

The correct way of copying an object is

 from copy import copy
 a = [1, 2, 3]
 b = copy(a)

Pretty simple. There is shortcuts for lists:

 a = [1, 2, 3]
 b = a[:]

There is also deepcopy() if you want to copy the objects in the list as well.