Trong lập trình, đặc biệt là khi làm việc với các cấu trúc dữ liệu phức tạp như danh sách (list), từ điển (dictionary) hay các đối tượng (objects), bạn thường xuyên phải đối mặt với khái niệm sao chép dữ liệu. Hai thuật ngữ quan trọng liên quan đến việc sao chép dữ liệu là Deep Copy và Shallow Copy. Bài viết này sẽ giúp bạn hiểu rõ về sự khác biệt giữa chúng và khi nào nên sử dụng từng loại.
1. Khái niệm cơ bản
Shallow Copy (Sao chép nông)
Shallow Copy là quá trình tạo ra một bản sao của đối tượng, nhưng chỉ sao chép các tham chiếu (references) đến các đối tượng con mà không tạo ra các bản sao mới của các đối tượng con đó. Nói cách khác, đối tượng mới và đối tượng gốc sẽ cùng tham chiếu đến cùng một đối tượng con.
Cách hoạt động của Shallow Copy:
Tạo một bản sao của đối tượng gốc.
Các thuộc tính của đối tượng gốc được sao chép, nhưng các tham chiếu đến các đối tượng con (nếu có) chỉ là các tham chiếu, không phải các bản sao mới.
Ví dụ:
import copy
original_list = [[1, 2, 3], [4, 5, 6]]
shallow_copied_list = copy.copy(original_list)
# Thay đổi trong shallow_copied_list ảnh hưởng đến original_list
shallow_copied_list[0][0] = 'X'
print("Original List:", original_list) # Kết quả: [['X', 2, 3], [4, 5, 6]]
print("Shallow Copied List:", shallow_copied_list) # Kết quả: [['X', 2, 3], [4, 5, 6]]
Trong ví dụ trên, thay đổi đối tượng con trong shallow_copied_list
cũng ảnh hưởng đến original_list
vì chúng cùng tham chiếu đến cùng một đối tượng con.
Deep Copy (Sao chép sâu)
Deep Copy là quá trình tạo ra một bản sao của đối tượng gốc cùng với tất cả các đối tượng con của nó. Nói cách khác, đối tượng mới sẽ có các bản sao hoàn toàn độc lập của tất cả các đối tượng con.
Cách hoạt động của Deep Copy:
Tạo một bản sao của đối tượng gốc.
Tạo các bản sao mới cho tất cả các đối tượng con mà đối tượng gốc tham chiếu đến.
Ví dụ:
import copy
original_list = [[1, 2, 3], [4, 5, 6]]
deep_copied_list = copy.deepcopy(original_list)
# Thay đổi trong deep_copied_list không ảnh hưởng đến original_list
deep_copied_list[0][0] = 'X'
print("Original List:", original_list) # Kết quả: [[1, 2, 3], [4, 5, 6]]
print("Deep Copied List:", deep_copied_list) # Kết quả: [['X', 2, 3], [4, 5, 6]]
Trong ví dụ trên, thay đổi đối tượng con trong deep_copied_list
không ảnh hưởng đến original_list
vì deep_copied_list
có các bản sao độc lập của tất cả các đối tượng con.
2. Sự khác biệt chính
Shallow Copy chỉ sao chép các tham chiếu đến các đối tượng con, trong khi Deep Copy sao chép cả các đối tượng con.
Thay đổi đối tượng con trong Shallow Copy sẽ ảnh hưởng đến đối tượng gốc, trong khi Deep Copy hoàn toàn độc lập.
3. Khi nào nên sử dụng Shallow Copy hoặc Deep Copy
Sử dụng Shallow Copy khi bạn chỉ cần sao chép đối tượng mà không cần tạo ra các bản sao độc lập của các đối tượng con. Điều này giúp tiết kiệm tài nguyên bộ nhớ và thời gian xử lý khi đối tượng con không cần thay đổi độc lập.
Sử dụng Deep Copy khi bạn cần tạo ra một bản sao hoàn toàn độc lập của đối tượng, bao gồm tất cả các đối tượng con. Điều này hữu ích khi bạn cần thao tác với các bản sao mà không làm ảnh hưởng đến đối tượng gốc.
4. Kết luận
Hiểu rõ về Shallow Copy và Deep Copy giúp bạn có thể lựa chọn phương pháp sao chép phù hợp trong các tình huống khác nhau. Shallow Copy tiết kiệm tài nguyên nhưng có thể dẫn đến các vấn đề không mong muốn nếu các đối tượng con bị thay đổi, trong khi Deep Copy cung cấp sự độc lập hoàn toàn nhưng yêu cầu nhiều tài nguyên hơn. Tùy thuộc vào yêu cầu của ứng dụng của bạn, bạn sẽ chọn phương pháp sao chép phù hợp để đảm bảo sự chính xác và hiệu suất.
Kết nối với web designer Lê Thành Nam