Home  >  Article  >  Backend Development  >  Detailed explanation of Python shallow copy, deep copy and reference mechanism

Detailed explanation of Python shallow copy, deep copy and reference mechanism

高洛峰
高洛峰Original
2017-03-23 17:43:071365browse

I encountered some problems this week, and then I realized that if the basic knowledge has not been consolidated for a period of time, there are still forgotten parts that still need to be reviewed. I will make a note here to record it

Previous Continue

Let’s briefly describe the problem encountered. The requirement is to write the results of 2 prints

详解Python浅拷贝、深拷贝及引用机制

As you can see, a points to a list list object, in Python, such an assignment statement actually means that a points to the memory address where the list is located, which can be regarded as a concept similar to a pointer.

And b, please note that it wraps the a object into a list and multiplies it by 5, so b should look like a big list with all the elements in it. When the a object After the append operation is performed, in fact, the implicit meaning is that the list in the memory has been modified, and all objects that reference this object will change

I print out the id of a, and , and print the id of element a contained in the object b, so that you can see that in the list b, the id of each element is the same as a



详解Python浅拷贝、深拷贝及引用机制 We can see that the id (memory address) of object a is 10892296. Although b wraps a into a new list, this element still refers to the object with the same address. This can be explained by the following figure



详解Python浅拷贝、深拷贝及引用机制 After that, we performed the append operation on a. Since list is a variable object, its memory address has not changed, but the reference to this address in the memory All objects will be changed together, which can be seen from the lower half of the dividing line in the test chart above.

This leads to a review of the Python reference mechanism and shallow copy and deep copy


Python’s reference mechanism



Reference mechanism case 1
From the above example, we can see that python Pass by reference, the final result is to have two objects refer to the contents of the same area in the memory

So let's take a look at the following example

B passes A, and also references the id of 17446024 The content of the address and the ID (memory address) of the two are exactly the same

So, through the operation of A A[0]=3 or A[3].append(6), it will be correct The contents in this memory are modified (because list is a variable object, so the memory address will not change, which will be discussed later)

This is the most basic reference case (in addition, since A and B all points to the same memory address, so the content modified by B can also be reflected on A)



详解Python浅拷贝、深拷贝及引用机制
Reference mechanism case 2
Let’s look at another case

Looking at the question, it seems that element 2 will be replaced with the list itself. The result may be A=[1,[1,2,3],3]

But it’s not! ! You can see that in the red box, there are infinite number of nested

Why is this happening?

In fact, it is because A points to the list [1,2,3]. In this example, only the second element of A points to the A object itself, so it is only the second element of A. The structure has changed! However, A still points to that object

We can see by printing the id of A that its pointing has not changed! !



详解Python浅拷贝、深拷贝及引用机制 Let’s take a look, the direction of A has not changed



详解Python浅拷贝、深拷贝及引用机制 Then if we want to achieve the final output effect, it is [ 1, [1,2,3],3], how should we operate it?

Here, we will use shallow copy. The usage can be as follows




详解Python浅拷贝、深拷贝及引用机制
Shallow copy and deep copy

Shallow copy

Now, let’s talk about shallow copy and deep copy. The above method actually only performs shallow copy, shallow copy, which means that it copies the original referenced object, but no longer references the same object address

Look at the example below. B performs a shallow copy through the B = A[:] operation. You can see that after the shallow copy, the memory addresses referenced by A and B are already different

However, the reference addresses of the elements inside A and B are still the same, so be very careful about this! There is a difference! ! !

The difference in the reference memory addresses of A and B means that the operation you perform on B will not affect A.

详解Python浅拷贝、深拷贝及引用机制

Shallow copy summary:

So shallow copy can be summarized as copying a reference, the new object and the original The object references are distinguished, but the address references of the internal elements are still the same

But shallow copying will also have problems. What is the problem? It is when there is nesting. For example, as you can see in the following situation, I assigned a shallow copy of A to B, so that the IDs (memory addresses) of A and B are different.

So, when I modify A[0]=8, B will not be affected, because A and B are independent references, but there is a nested list in the middle [4 ,5,6]

We can understand this [4,5,6] as: A and B still reference together, that is, for the second elements of A and B, they still point to the same A memory address.

In addition, since int is an immutable type, after changing A[0] to 8, its reference address will change! It is distinguished from the reference of the element B[0].

详解Python浅拷贝、深拷贝及引用机制

Deep Copy

So how to face such a situation? We need to use the copy module in the python module

The copy module has 2 functions

1: copy.copy (the object you want to copy): This is a shallow copy, and the previous one The nature of the [:] operation on the list is the same

2: copy.deepcopy (the object you want to copy): This is a deep copy, except that it will generate a new object just like the shallow copy. References, and for internal elements, new references will be generated to separate them independently.

Look at the example below, when you assign a deep copy of A to B, they can be said to be completely independent. , whether you modify the immutable elements in A, or modify the nested mutable elements in A, the result will not affect B

My understanding is: deep copy can be called recursive copy, He will copy all nested variable elements and then reference them independently.

详解Python浅拷贝、深拷贝及引用机制

Deep copy summary:

The effect of deep copy is the same as that of shallow copy. In addition to generating a new reference from the object's reference, it will help you open all the nested elements one by one.

I drew 2 pictures myself Figure to show the difference between the effects of shallow copy and deep copy

It should be noted that although after shallow copy, the reference address of the immutable elements in the list is still the same, but because they are immutable elements, Therefore, after any immutable element is changed, the reference address will be new without affecting the original reference address.



详解Python浅拷贝、深拷贝及引用机制

详解Python浅拷贝、深拷贝及引用机制

##Summary
So, here we go, shallow copy And the mechanism of deep copy is basically understood.

There are also special circumstances that need to be explained

For immutable types: int, str, tuple, float and other elements, there is no copy. After they are modified, the reference address is Directly changed, as shown below


详解Python浅拷贝、深拷贝及引用机制
However, if there are nested variable types inside the immutable type, you can still use deep copy

详解Python浅拷贝、深拷贝及引用机制

Also a reminder, the method we usually use most is direct assignment (or direct passing of references), such as the following example

He combines a and b Two variable elements point to a memory address at the same time, so any change will affect a and b

详解Python浅拷贝、深拷贝及引用机制

Finally

Variable type: list , set, dict

Immutable types: int, str, float, tuple

Shallow copy method: [:], copy.copy(), use factory function (list/dir/set )

Deep copy method: copy.deepcopy()


The above is the detailed content of Detailed explanation of Python shallow copy, deep copy and reference mechanism. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn