Introduction to assignment shallow copy and deep copy in Python

  • 2020-04-02 14:37:53
  • OfStack

Like many languages, Python is divided into simple assignment, shallow copy, and deep copy.

During the learning process, the understanding of shallow copy was very vague at first. However, after a series of experiments, I found that I have a better understanding of the three concepts.

One, the assignment

Assignment is the most common of these three operations. Let's analyze the assignment operation with some examples:

In the STR


>>> a = 'hello'
>>> b = 'hello'
>>> c = a
>>> [id(x) for x in a,b,c]
[4404120000, 4404120000, 4404120000]

From the above instructions, we can find that the addresses of a, b and c are the same. So the assignment above is the same as c = a = b = 'hello'.

Assignment is when the system allocates memory to a variable or object (in this case, 'hello') and then assigns the address to a, b, and c. So they have the same address.

In the list


>>> a = ['hello']
>>> b = ['hello']
>>> c = a
>>> [id(x) for x in a,b,c]
[4403975952, 4404095096, 4403975952]

But in this case, a and b have different addresses. Why?

Because STR is immutable, there is only one address for the same 'hello', but list is mutable, so you must assign two addresses.

At this point, we want to explore both of these scenarios and what happens if we change the value?

In the STR


>>> a = 'world'
>>> [id(x) for x in a,b,c]
[4404120432, 4404120000, 4404120000]
>>> print a, b, c
world hello hello

The address and the value of a change, but the address and the value of b and c do not change. Because of the immutability of STR, a has to re-allocate memory space for reassignment, so the value of a changes and the address of a changes. B, c doesn't change because of the invariance of 'hello'.

In the list


>>> a[0] = 'world'
>>> [id(x) for x in a,b,c]
[4403975952, 4404095096, 4403975952]
>>> print a, b, c
['world'] ['hello'] ['world']

The values and addresses of a and c change, but they're still the same. B doesn't change. Because of the variability of the list, modifying the value of the list does not require additional space, just changing the value of the original address. So a and c change.

After understanding the above differences, we can analyze the shallow copy and the deep copy very well.

We all use list as an example.

Two, shallow copy


>>> a = ['hello', [123, 234]]
>>> b = a[:]
>>> [id(x) for x in a,b]
[4496003656, 4496066752]
>>> [id(x) for x in a]
[4496091584, 4495947536]
>>> [id(x) for x in b]
[4496091584, 4495947536]

Line3,4 can see that a, b address is different, which conforms to the list is variable, should open up different space. Is the shallow copy a copy? Looking at line5-8, we see that the addresses of the elements in a and b are the same. It makes sense if the string 'hello' addresses are the same, but the second element is that the list addresses are still the same. This illustrates the shallow-copy feature, which simply copies the address of the element in the container.

Then we try to modify the values in a and b:


>>> a[0] = 'world'
>>> a[1].append(345)
>>> print 'a = ', a, 'nr', 'b = ', b
a =  ['world', [123, 234, 345]]
b =  ['hello', [123, 234, 345]]

The first element in a, STR, changes, but not in b; The second element in a changes, and the second element in b changes. This is consistent with immutable object modifications opening up new space, mutable object modifications opening up no new space. It further proves that the shallow copy simply copies the address of the element in the container.

Three, deep copy


>>> from copy import deepcopy
>>> a = ['hello', [123, 234]]
>>> b = deepcopy(a)
>>> [id(x) for x in a, b]
[4496066824, 4496066680]
>>> [id(x) for x in a]
[4496091584, 4496067040]
>>> [id(x) for x in b]
[4496091584, 4496371792]

After deep copying, you can find that the addresses of a, b and elements in a and b are different. This is a full copy.

After modifying the value of a:


>>> a[0] = 'world'
>>> a[1].append(345)
>>> print 'a = ', a, 'nr', 'b = ', b
a =  ['world', [123, 234, 345]]
b =  ['hello', [123, 234]]

It can be found from Line4 and 5 that only a has changed and b has not changed at all. Because b is a complete copy, the element address is different from a, a modification, b is not affected.

Conclusion:

1. Assignment is to assign the address of an object to a variable that points to that address.

2. Shallow copy is to create a new variable or container in another address, but the addresses of the elements in the container are copies of the addresses of the elements of the source object. In other words, the new container points to the old element.

3. Deep copy is to create a new variable or container in another address, and the address of the element in the container is also new, only the same value, is a complete copy. That is to say (new wine in new bottles).


Related articles: