In Python, to make a shallow and deep copy, use the copy()
method of lists list
, dictionaries dict
, etc., or the copy()
and deepcopy()
functions of the copy module.
This article describes the following contents.
- Shallow copy and deep copy
- Assignment to another variable
- Shallow copy:
copy()
, copy.copy()
, etc. -
copy()
method of lists, dictionaries, etc. - Slice
-
list()
, dict()
, etc. copy.copy()
- Deep copy:
copy.deepcopy()
The following is a summary of the differences between assignment to another variable, shallow copy, and deep copy.
import copy l = [0, 1, [2, 3]] l_assign = l # assignment l_copy = l.copy() # shallow copy l_deepcopy = copy.deepcopy(l) # deep copy l[1] = 100 l[2][0] = 200 print(l) # [0, 100, [200, 3]] print(l_assign) # [0, 100, [200, 3]] print(l_copy) # [0, 1, [200, 3]] print(l_deepcopy) # [0, 1, [2, 3]]
Shallow copy and deep copy
The explanation of shallow copy and deep copy in the official documentation is as follows.
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.copy — Shallow and deep copy operations — Python 3.9.6 documentation
For objects in mutable objects such as lists and dictionaries (= elements in a list or values in a dictionary), shallow copy inserts references and deep copy inserts copies. In the case of references, they are the same object, so if one of them is changed, the other will also be changed.
Assignment to another variable
First, let's see what happens when assigning to a variable.
When a mutable object such as a list or a dictionary is assigned to multiple variables, updating one variable (= changing, adding, or deleting elements, etc.) will also update the other variables.
l1 = [0, 1, [2, 3]] l2 = l1 print(l1 is l2) # True l1[1] = 100 l1[2][0] = 200 print(l1) # [0, 100, [200, 3]] print(l2) # [0, 100, [200, 3]] print(l1 is l2) # True
As you can see from the result of is
, the two variables refer to the same object both before and after the value is changed.
To create a copy instead of a reference of the same object, use the copy()
method or the copy.deepcopy()
function described below.
On the other hand, in the case of immutable objects such as numbers int
, float
and strings str
, the value of the object cannot be updated. When assigned, the two variables are the same object, but when one is updated to a new value, it becomes a different object and the other remains the same.
i1 = 1 i2 = i1 print(i1 is i2) # True i1 += 100 print(i1) # 101 print(i2) # 1 print(i1 is i2) # False
Shallow copy: copy()
, copy.copy()
, etc.
copy()
method of lists, dictionaries, etc.
The copy()
method is provided for lists, dictionaries, etc. The copy()
method makes a shallow copy.
As mentioned above, a shallow copy inserts a reference to an object in the original object. For example, in the case of a shallow copy of a list, the list itself will be a different object, but its elements are references to the same objects in the elements of the original list.
l = [0, 1, [2, 3]] l_copy = l.copy() print(l is l_copy) # False print(l[2] is l_copy[2]) # True
Therefore, if the elements are mutable, when one is updated, the other is also updated. In the case of an immutable, when it is updated to a new value, it becomes a different object, and the other remains the original.
l[1] = 100 l[2][0] = 200 print(l) # [0, 100, [200, 3]] print(l_copy) # [0, 1, [200, 3]] print(l[2] is l_copy[2]) # True
The same applies not only to lists of lists as in the example above, but also to lists of dictionaries, nested dictionaries (dictionaries of dictionaries), etc.
Slice
Slices for mutable sequence types, such as lists, also make shallow copies.
For example, applying the slice [:]
that specifies all elements makes a shallow copy of the whole list.
l = [0, 1, [2, 3]] l_whole_slice = l[:] l[1] = 100 l[2][0] = 200 print(l) # [0, 100, [200, 3]] print(l_whole_slice) # [0, 1, [200, 3]]
Since the copy()
method was added to mutable sequence types in Python 3.3, the technique of making a shallow copy with [:]
was used before that. For new code, it would be better to use the copy()
method to make your intentions clearer.
A slice for a part also makes a shallow copy.
l = [0, 1, [2, 3]] l_slice = l[1:] print(l_slice) # [1, [2, 3]] l[1] = 100 l[2][0] = 200 print(l) # [0, 100, [200, 3]] print(l_slice) # [1, [200, 3]]
If you want to make a deep copy, you can apply the copy.deepcopy()
function to the slice.
list()
, dict()
, etc.
You can make a shallow copy of a list or dictionary by passing a list to list()
or a dictionary to dict()
.
l = [0, 1, [2, 3]] l_list = list(l) l[1] = 100 l[2][0] = 200 print(l) # [0, 100, [200, 3]] print(l_list) # [0, 1, [200, 3]]
copy.copy()
It is also possible to make a shallow copy with the copy()
function of the copy module.
l = [0, 1, [2, 3]] l_copy = copy.copy(l) l[1] = 100 l[2][0] = 200 print(l) # [0, 100, [200, 3]] print(l_copy) # [0, 1, [200, 3]]
Use copy.copy()
if you want to make a shallow copy of an object for which the copy()
method is not provided.
Deep copy: copy.deepcopy()
To make a deep copy, use the deepcopy()
function of the copy module.
l = [0, 1, [2, 3]] l_deepcopy = copy.deepcopy(l) print(l is l_deepcopy) # False print(l[2] is l_deepcopy[2]) # False l[1] = 100 l[2][0] = 200 print(l) # [0, 100, [200, 3]] print(l_deepcopy) # [0, 1, [2, 3]]
In a deep copy, copies are inserted instead of references to objects, so changing one does not change the other.
The following is an example of applying the deepcopy()
function to a slice.
l = [0, 1, [2, 3]] l_slice_deepcopy = copy.deepcopy(l[1:]) print(l_slice_deepcopy) # [1, [2, 3]] l[1] = 100 l[2][0] = 200 print(l) # [0, 100, [200, 3]] print(l_slice_deepcopy) # [1, [2, 3]]
Source:
https://note.nkmk.me/en/python-copy-deepcopy/
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.