Deep Copy và Shallow Copy trong Python

Trong Python, các câu lệnh gán không sao chép các đối tượng, chúng chỉ tạo ra các ràng buộc giữa đích và một đối tượng. Khi chúng ta sử dụng toán tử "=" người ta vẫn nghĩ rằng sẽ tạo ra một đối tượng mới. Ồ nhưng thật ra thì không. Nó chỉ tạo ra một biến mới chia sẻ tham chiếu của đối tượng ban đầu. Đôi khi, một người dùng muốn làm việc với các đối tượng có thể thay đổi, để làm điều đó, người dùng sẽ tìm cách tạo ra các bản sao thực sự của bản sao hoặc các bản sao của các đối tượng này Một bản sao đôi khi là cần thiết để người ta có thể thay đổi một bản sao mà không thay đổi bản sao khác. Trong Python, có hai cách để tạo bản sao(dịch ra Tiếng Việt có vẻ hơi tối nghĩa)

  • Deep copy (Sao chép sâu)
  • Shallow copy (Sao chép nông)
  • Để tạo ra các bản sao này, chúng ta sử dụng module "copy". Chúng ta sử dụng module "copy" cho các hoạt động sao chép nông và sâu. Ví dụ:
# importing copy module 
import copy 
  
# initializing list 1  
li1 = [1, 2, [3,5], 4] 
  
  
# using copy for shallow copy   
li2 = copy.copy(li1)  
  
# using deepcopy for deepcopy   
li3 = copy.deepcopy(li1)  

Trong đoạn code trên, copy () trả về một bản sao nông của danh sách và deepcopy () trả về một bản sao sâu của danh sách.

1. Shallow copy

Trong trường hợp sao chép sâu, một bản sao của đối tượng được sao chép trong đối tượng khác. Có nghĩa là bất kỳ thay đổi được thực hiện cho một bản sao của đối tượng không phản ánh trong đối tượng ban đầu. Trong python, điều này được thực hiện bằng cách sử dụng hàm deepcopy ().

# Python code to demonstrate copy operations 
  
# importing "copy" for copy operations 
import copy 
  
# initializing list 1 
li1 = [1, 2, [3,5], 4] 
  
# using deepcopy to deep copy  
li2 = copy.deepcopy(li1) 
  
# original elements of list 
print ("The original elements before deep copying") 
for i in range(0,len(li1)): 
    print (li1[i],end=" ") 
  
print("\r") 
  
# adding and element to new list 
li2[2][0] = 7
  
# Change is reflected in l2  
print ("The new list of elements after deep copying ") 
for i in range(0,len( li1)): 
    print (li2[i],end=" ") 
  
print("\r") 
  
# Change is NOT reflected in original list 
# as it is a deep copy 
print ("The original elements after deep copying") 
for i in range(0,len( li1)): 
    print (li1[i],end=" ") 

Output:

The original elements before deep copying
1 2 [3, 5] 4 
The new list of elements after deep copying 
1 2 [7, 5] 4 
The original elements after deep copying
1 2 [3, 5] 4 

Trong ví dụ trên, thay đổi được thực hiện trong danh sách không có hiệu lực trong các danh sách khác, điều này cho thấy danh sách được sao chép sâu

2. Shallow copy

Một bản sao nông có nghĩa là xây dựng một đối tượng mới và sau đó đưa vào đó các tham chiếu đến các đối tượng con được tìm thấy trong bản gốc. Quá trình sao chép không tái diễn và do đó tạo ra các bản sao của chính các đối tượng con. Trong trường hợp sao chép nông, một tham chiếu của đối tượng được sao chép trong đối tượng khác. Có nghĩa là bất kỳ thay đổi nào được thực hiện đối với một bản sao của đối tượng đều phản ánh trong đối tượng ban đầu. Trong python, điều này được thực hiện bằng cách sử dụng hàm copy():

# Python code to demonstrate copy operations 
  
# importing "copy" for copy operations 
import copy 
  
# initializing list 1 
li1 = [1, 2, [3,5], 4] 
  
# using copy to shallow copy  
li2 = copy.copy(li1) 
  
# original elements of list 
print ("The original elements before shallow copying") 
for i in range(0,len(li1)): 
    print (li1[i],end=" ") 
  
print("\r") 
  
# adding and element to new list 
li2[2][0] = 7
  
# checking if change is reflected 
print ("The original elements after shallow copying") 
for i in range(0,len( li1)): 
    print (li1[i],end=" ") 

Output:

The original elements before shallow copying
1 2 [3, 5] 4 
The original elements after shallow copying
1 2 [7, 5] 4 

Trong ví dụ trên, thay đổi được thực hiện trong danh sách có hiệu lực trong danh sách khác, điều này cho biết danh sách bị sao chép nông.

Điều cần chú ý là:

  • Sự khác biệt giữa sao chép nông và sâu chỉ có liên quan đến các đối tượng ghép(các đối tượng có chứa các đối tượng khác, danh sách hoặc instant class):
  • Một bản sao nông xây dựng một đối tượng ghép mới và sau đó (trong phạm vi có thể) chèn các tham chiếu vào nó cho các đối tượng được tìm thấy trong bản gốc.
  • Một bản sao sâu xây dựng một đối tượng ghép mới và sau đó, đệ quy, chèn các bản sao vào đối tượng được tìm thấy trong bản gốc.

Tham khảo: https://www.geeksforgeeks.org/copy-python-deep-copy-shallow-copy/