Trong bài viết này, bạn sẽ tìm hiểu về bản sao nông và bản sao sâu trong Python với sự trợ giúp của các ví dụ.
Sao chép một đối tượng bằng Python
Trong Python, chúng ta sử dụng =
toán tử để tạo bản sao của một đối tượng. Bạn có thể nghĩ rằng điều này tạo ra một đối tượng mới; nó 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.
Hãy lấy một ví dụ trong đó chúng ta tạo một danh sách có tên old_list và chuyển một tham chiếu đối tượng tới new_list bằng =
toán tử.
Ví dụ 1: Sao chép bằng toán tử =
old_list = ((1, 2, 3), (4, 5, 6), (7, 8, 'a')) new_list = old_list new_list(2)(2) = 9 print('Old List:', old_list) print('ID of Old List:', id(old_list)) print('New List:', new_list) print('ID of New List:', id(new_list))
Khi chúng ta chạy chương trình trên, kết quả đầu ra sẽ là:
Danh sách Cũ: ((1, 2, 3), (4, 5, 6), (7, 8, 9)) ID của Danh sách Cũ: 140673303268168 Danh sách Mới: ((1, 2, 3), (4, 5 , 6), (7, 8, 9)) ID của danh sách mới: 140673303268168
Như bạn có thể thấy từ đầu ra, cả hai biến old_list và new_list đều chia sẻ cùng một id tức là 140673303268168
.
Vì vậy, nếu bạn muốn sửa đổi bất kỳ giá trị nào trong new_list hoặc old_list, thay đổi sẽ hiển thị trong cả hai.
Về cơ bản, đôi khi bạn có thể muốn giữ nguyên các giá trị ban đầu và chỉ sửa đổi các giá trị mới hoặc ngược lại. Trong Python, có hai cách để tạo bản sao:
- Sao chép nông
- Bản sao sâu
Để làm cho các bản sao này hoạt động, chúng tôi sử dụng copy
mô-đun.
Sao chép mô-đun
Chúng tôi sử dụng copy
mô-đun của Python cho các hoạt động sao chép nông và sâu. Giả sử, bạn cần sao chép danh sách ghép nói x. Ví dụ:
nhập bản sao copy.copy (x) copy.deepcopy (x)
Ở đây, copy()
trả về một bản sao nông của x. Tương tự, deepcopy()
trả về một bản sao sâu của x.
Sao chép nông
Một bản sao cạn tạo ra một đối tượng mới để lưu trữ tham chiếu của các phần tử gốc.
Vì vậy, một bản sao cạn không tạo ra một bản sao của các đối tượng lồng nhau, thay vào đó nó chỉ sao chép tham chiếu của các đối tượng lồng nhau. Điều này có nghĩa là, một quá trình sao chép không lặp lại hoặc tạo bản sao của chính các đối tượng lồng nhau.
Ví dụ 2: Tạo một bản sao bằng cách sử dụng bản sao nông
import copy old_list = ((1, 2, 3), (4, 5, 6), (7, 8, 9)) new_list = copy.copy(old_list) print("Old list:", old_list) print("New list:", new_list)
Khi chúng tôi chạy chương trình, đầu ra sẽ là:
Danh sách cũ: ((1, 2, 3), (4, 5, 6), (7, 8, 9)) Danh sách mới: ((1, 2, 3), (4, 5, 6), (7 , 8, 9))
Trong chương trình trên, chúng tôi đã tạo một danh sách lồng nhau và sau đó sao chép nó bằng copy()
phương thức.
Điều này có nghĩa là nó sẽ tạo đối tượng mới và độc lập với cùng nội dung. Để xác minh điều này, chúng tôi in cả old_list và new_list.
Để xác nhận rằng new_list khác với old_list, chúng tôi cố gắng thêm đối tượng lồng nhau mới vào đối tượng gốc và kiểm tra nó.
Ví dụ 3: Thêm (4, 4, 4) vào old_list, sử dụng bản sao cạn
import copy old_list = ((1, 1, 1), (2, 2, 2), (3, 3, 3)) new_list = copy.copy(old_list) old_list.append((4, 4, 4)) print("Old list:", old_list) print("New list:", new_list)
Khi chúng tôi chạy chương trình, nó sẽ xuất ra:
Danh sách cũ: ((1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4)) Danh sách mới: ((1, 1, 1), (2 , 2, 2), (3, 3, 3))
Trong chương trình trên, chúng tôi đã tạo một bản sao cạn của old_list. New_list chứa các tham chiếu đến các đối tượng lồng nhau ban đầu được lưu trữ trong old_list. Sau đó, chúng tôi thêm danh sách mới tức là (4, 4, 4)
vào old_list. Danh sách con mới này không được sao chép trong new_list.
Tuy nhiên, khi bạn thay đổi bất kỳ đối tượng lồng nhau nào trong old_list, các thay đổi sẽ xuất hiện trong new_list.
Ví dụ 4: Thêm đối tượng lồng nhau mới bằng cách sử dụng Bản sao nông
import copy old_list = ((1, 1, 1), (2, 2, 2), (3, 3, 3)) new_list = copy.copy(old_list) old_list(1)(1) = 'AA' print("Old list:", old_list) print("New list:", new_list)
Khi chúng tôi chạy chương trình, nó sẽ xuất ra:
Danh sách cũ: ((1, 1, 1), (2, 'AA', 2), (3, 3, 3)) Danh sách mới: ((1, 1, 1), (2, 'AA', 2 ), (3, 3, 3))
Trong chương trình trên, chúng tôi đã thực hiện các thay đổi đối với old_list tức là old_list(1)(1) = 'AA'
. Cả hai danh sách con của old_list và new_list tại chỉ mục (1)(1)
đều đã được sửa đổi. Điều này là do, cả hai danh sách đều chia sẻ tham chiếu của các đối tượng lồng nhau giống nhau.
Bản sao sâu
Bản sao sâu tạo ra một đối tượng mới và thêm đệ quy các bản sao của các đối tượng lồng nhau có trong các phần tử gốc.
Hãy tiếp tục với ví dụ 2. Tuy nhiên, chúng ta sẽ tạo bản sao sâu bằng cách sử dụng deepcopy()
hàm có trong copy
mô-đun. Bản sao sâu tạo ra bản sao độc lập của đối tượng gốc và tất cả các đối tượng lồng vào nhau của nó.
Ví dụ 5: Sao chép danh sách bằng deepcopy ()
import copy old_list = ((1, 1, 1), (2, 2, 2), (3, 3, 3)) new_list = copy.deepcopy(old_list) print("Old list:", old_list) print("New list:", new_list)
Khi chúng tôi chạy chương trình, nó sẽ xuất ra:
Danh sách cũ: ((1, 1, 1), (2, 2, 2), (3, 3, 3)) Danh sách mới: ((1, 1, 1), (2, 2, 2), (3 , 3, 3))
Trong chương trình trên, chúng ta sử dụng deepcopy()
hàm để tạo bản sao trông tương tự.
Tuy nhiên, nếu bạn thực hiện thay đổi đối với bất kỳ đối tượng lồng nhau nào trong đối tượng gốc old_list, bạn sẽ không thấy thay đổi nào đối với bản sao new_list.
Ví dụ 6: Thêm một đối tượng lồng nhau mới vào danh sách bằng cách sử dụng Bản sao sâu
import copy old_list = ((1, 1, 1), (2, 2, 2), (3, 3, 3)) new_list = copy.deepcopy(old_list) old_list(1)(0) = 'BB' print("Old list:", old_list) print("New list:", new_list)
Khi chúng tôi chạy chương trình, nó sẽ xuất ra:
Danh sách cũ: ((1, 1, 1), ('BB', 2, 2), (3, 3, 3)) Danh sách mới: ((1, 1, 1), (2, 2, 2), (3, 3, 3))
Trong chương trình trên, khi chúng ta gán một giá trị mới cho old_list, chúng ta chỉ có thể thấy old_list được sửa đổi. Điều này có nghĩa là, cả old_list và new_list đều độc lập. Điều này là do old_list đã được sao chép đệ quy, điều này đúng với tất cả các đối tượng lồng nhau của nó.