Cách sao chép danh sách trong Python (Bản sao nông so với bản sao sâu)

Tìm hiểu cách sao chép danh sách trong Python. Khám phá việc cắt danh sách, phương thức copy(), hàm tạo danh sách và nắm vững sự khác biệt giữa các bản sao nông và sâu.

Hãy thử Giải pháp này trong Trình chỉnh sửa

Tổng quan

Trong Python, danh sách là các đối tượng có thể thay đổi và các biến giữ các tham chiếu đến các đối tượng này trong bộ nhớ thay vì các giá trị thực. Điều này có nghĩa là nếu bạn gán một danh sách cho một biến mới (ví dụ: `list_b = list_a`), thì cả hai biến đều tham chiếu đến cùng một danh sách. Bất kỳ sửa đổi nào được thực hiện thông qua `list_b` sẽ ngay lập tức ảnh hưởng đến `list_a`. Để tránh tác dụng phụ này, bạn phải tạo một bản sao rõ ràng của danh sách.

Python cung cấp một số cách để tạo bản sao nông của danh sách. Một bản sao nông sẽ xây dựng một danh sách mới chứa các tham chiếu đến các phần tử được tìm thấy trong danh sách ban đầu. Các phương thức phổ biến bao gồm sử dụng phương thức `.copy()` danh sách tích hợp sẵn, sử dụng cắt danh sách `list_a[:]` hoặc chuyển danh sách tới hàm tạo `list()`. Tất cả những điều này tạo ra một vùng chứa danh sách mới, cho phép bạn thêm hoặc xóa các phần tử một cách độc lập.

Tuy nhiên, nếu một danh sách chứa các đối tượng có thể thay đổi lồng nhau (như danh sách hoặc từ điển), một bản sao nông sẽ chỉ sao chép vùng chứa bên ngoài; các đối tượng lồng nhau vẫn được chia sẻ. Việc sửa đổi danh sách lồng nhau trong bản sao sẽ làm thay đổi danh sách gốc. Để ngăn chặn điều này, bạn phải thực hiện sao chép sâu bằng cách sử dụng hàm `deepcopy()` của mô-đun `copy`, hàm này sẽ sao chép đệ quy mọi đối tượng bên trong hệ thống phân cấp.

Đầu ra mã & thực thi

Mã này thể hiện bẫy gán tham chiếu, sao chép nông bằng cách sử dụng list.copy() và sao chép sâu các danh sách lồng nhau bằng mô-đun sao chép.

import copy

# 1. The assignment reference trap (Not a copy!)
original = [1, 2, 3]
reference = original
reference.append(99)
print("Reference modification affects original:", original)

# Reset list
original = [1, 2, 3]

# 2. Creating a shallow copy (using list.copy())
shallow_copy = original.copy()
shallow_copy.append(100)
print("\nOriginal:", original)
print("Shallow copy:", shallow_copy)

# 3. The nested list limitation of shallow copies
nested = [[1, 2], [3, 4]]
shallow_nested = nested.copy()
shallow_nested[0].append(99) # Modifying nested list
print("\nOriginal nested:", nested)
print("Shallow nested copy:", shallow_nested)

# 4. Creating a deep copy
nested_original = [[1, 2], [3, 4]]
deep_copy = copy.deepcopy(nested_original)
deep_copy[0].append(99)
print("\nOriginal nested:", nested_original)
print("Deep copy (completely independent):", deep_copy)
Đầu ra thiết bị đầu cuối
Reference modification affects original: [1, 2, 3, 99]

Original: [1, 2, 3]
Shallow copy: [1, 2, 3, 100]

Original nested: [[1, 2, 99], [3, 4]]
Shallow nested copy: [[1, 2, 99], [3, 4]]

Original nested: [[1, 2], [3, 4]]
Deep copy (completely independent): [[1, 2, 99], [3, 4]]

Triển khai từng bước

  • Sử dụng my_list.copy() hoặc my_list[:] để tạo bản sao nông của cấu trúc danh sách phẳng.
  • Tránh các phép gán tham chiếu như copy_list = my_list khi bạn cần các bộ sưu tập độc lập.
  • Nhập mô-đun sao chép và sử dụng copy.deepcopy(my_list) cho các danh sách chứa các cấu trúc có thể thay đổi lồng nhau.
  • Đảm bảo bạn hiểu cấu trúc dữ liệu của mình để tối ưu hóa hiệu suất và dung lượng bộ nhớ.

Câu hỏi thường gặp

Sự khác biệt giữa bản sao nông và bản sao sâu là gì?

Một bản sao nông sao chép vùng chứa ngoài cùng nhưng tham chiếu đến các đối tượng có thể thay đổi lồng nhau. Một bản sao sâu sao chép đệ quy tất cả các vùng chứa và đối tượng lồng nhau, dẫn đến cấu trúc dữ liệu hoàn toàn tách biệt.

Việc cắt danh sách (list[:]) có nhanh hơn list.copy() không?

Chúng hầu như giống nhau về hiệu suất vì cả hai đều thực hiện các hoạt động C được tối ưu hóa. Sử dụng list.copy() thường được ưu tiên để dễ đọc.

Chủ đề liên quan

Tài nguyên Python được đề xuất

Mở rộng kiến thức của bạn với các hướng dẫn tương tác, bảng ghi chú và so sánh mã có liên quan.