Computer >> Máy Tính >  >> Lập trình >> Python

Sao chép - Các thao tác sao chép nông và sâu trong Python

Trong Python, một biến chỉ là một tham chiếu đến đối tượng. Do đó, khi nó được gán cho một biến khác, nó sẽ không sao chép đối tượng, thay vào đó nó hoạt động như một tham chiếu khác đến cùng một đối tượng. Điều này có thể được xác minh bằng cách sử dụng hàm id ()

>>> L1 = [1,2,3]
>>> L2 = L1
>>> id(L1), id(L2)
(2165544063496, 2165544063496)

Kết quả của đoạn mã trên cho thấy rằng id () cho cả hai đối tượng danh sách là giống nhau, có nghĩa là cả hai đều tham chiếu đến cùng một đối tượng. L2 được cho là một bản sao nông của L1. Vì cả hai đều tham chiếu đến cùng một đối tượng nên bất kỳ thay đổi nào trong một trong hai sẽ phản ánh trong đối tượng khác.

>>> L1 = [1,2,3]
>>> L2 = L1
>>> L2[1] = 100
>>> L1,L2
([1, 100, 3], [1, 100, 3])

Trong ví dụ trên, mục ở chỉ mục số. 1 trong số L2 được thay đổi. Chúng tôi thấy sự thay đổi này xuất hiện ở cả hai.

Khi một đối tượng hoàn toàn mới được tạo bằng thao tác sao chép, với các bản sao của các đối tượng lồng nhau cũng được thêm vào nó một cách đệ quy, bản sao được gọi là bản sao sâu.

Mô-đun sao chép của thư viện chuẩn Python cung cấp hai phương thức:

  • copy.copy () - tạo một bản sao cạn
  • copy.deepcopy () - tạo một bản sao sâu

Bản sao cạn tạo ra một đối tượng mới và lưu trữ tham chiếu của các phần tử gốc nhưng không tạo bản sao của các đối tượng lồng nhau. Nó chỉ sao chép tham chiếu của các đối tượng lồng nhau. Do đó, quá trình sao chép không phải là đệ quy.

>>> import copy
>>> L1 = [[1,2,3], [4,5,6]]
>>> L2 = copy.copy(L1)
>>> L1,L2
([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]])
>>> L2.append([10,10,10])
>>> L1,L2
([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6], [10, 10, 10]])

Ở đây L1 là một danh sách lồng nhau và L2 là bản sao cạn của nó. Mặc dù tham chiếu đến đối tượng danh sách mẹ được sao chép vào L2, các phần tử lồng nhau của nó không được sao chép. Do đó, khi chúng tôi thêm một danh sách khác vào L2, danh sách đó không được phản ánh trong L1

Tuy nhiên, nếu chúng tôi cố gắng sửa đổi một phần tử trong phần tử con, hiệu ứng của nó sẽ được nhìn thấy trong cả hai danh sách

>>> L1 = [[1,2,3], [4,5,6]]
>>> L2 = copy.copy(L1)
>>> L1,L2
([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]])
>>> L2[1][0] = 100
>>> L1,L2
([[1, 2, 3], [100, 5, 6]], [[1, 2, 3], [100, 5, 6]])

Tuy nhiên, một 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.

Trong ví dụ sau, L2 là một bản sao sâu của L2. Bây giờ nếu chúng ta thay đổi bất kỳ phần tử nào của danh sách bên trong, phần tử này sẽ không hiển thị trong danh sách khác.

>>> L1 = [[1,2,3], [4,5,6]]
>>> L2 = copy.deepcopy(L1)
>>> L1,L2
([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]])
>>> L2[1][0] = 100
>>> L1,L2
([[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [100, 5, 6]])

Do đó, tác dụng của bản sao sâu được xác minh bởi đầu ra.