Python sao chép nông hay sâu?
Python đi kèm với một mô-đun có tên là >>> a = a + 1 7 cung cấp chức năng sao chép nhất định. Trong bài viết này, chúng ta sẽ khám phá những bản sao sâu và nông là gì. Ngoài ra, chúng ta sẽ thảo luận về sự khác biệt của chúng và khi nào nên sử dụng cái này hơn cái kia Show Các đối tượng không thể thay đổi so với có thể thay đổiTrước khi chuyển sang các bản sao nông và sâu trong Python, điều quan trọng trước tiên là phải hiểu sự khác biệt giữa các loại đối tượng có thể thay đổi và không thể thay đổi. Như tên cho thấy, các đối tượng bất biến không thể thay đổi được và do đó, thay vào đó, Python sẽ tạo một đối tượng mới khi giá trị của đối tượng đó bị sửa đổi Chẳng hạn, giả sử rằng chúng ta có hai biến tham chiếu đến cùng một đối tượng số nguyên >>> a = 10 Bây giờ nếu chúng ta thực hiện bất kỳ loại thao tác nào trên biến >>> a = a + 1 8— và cho rằng các số nguyên trong Python là bất biến — kết quả về cơ bản sẽ là một đối tượng mới chứa giá trị mới. Điều này có nghĩa là giá trị cũ của đối tượng (và do đó tất cả các biến tham chiếu đến nó), sẽ không thay đổi>>> a = a + 1 Mặt khác, các loại đối tượng có thể thay đổi cho phép sửa đổi tại chỗ giá trị đối tượng. Điều này có nghĩa là khi giá trị của một loại đối tượng có thể thay đổi được sửa đổi, sẽ có tác động đến tất cả các biến đang giữ tham chiếu đến cùng một đối tượng. Chẳng hạn, giả sử chúng ta có các danh sách sau >>> list_1 = [1, 2, 3] Vì các danh sách trong Python có thể thay đổi, nếu chúng ta thay đổi bất kỳ danh sách nào trong hai danh sách thì hành động này cũng sẽ có tác động trực tiếp đến biến kia, vì cả hai đều trỏ đến cùng một tham chiếu đối tượng trong bộ nhớ >>> list_1[0] = 0 Để biết thêm chi tiết về mô hình Dynamic Typing của Python, bạn có thể đọc một trong những bài viết của tôi tại đây trên Medium Nhập động trong Pythonlà gốc rễ của tính linh hoạt của ngôn ngữhướng tới khoa học dữ liệu. com Bài tập bình thườngCách tiếp cận đơn giản nhất để sao chép các đối tượng là thông qua các hoạt động gán thông thường. Giả sử rằng chúng ta có các thao tác sau a = [1, 2, 3] Trong trường hợp này, cả hai biến >>> a = a + 1 8 và >>> list_1 = [1, 2, 3] 0 đều giữ cùng một tham chiếu đến cùng một đối tượng. Điều này có nghĩa là nếu bất kỳ biến nào trong hai biến được sử dụng để thực hiện sửa đổi tại chỗ, thì biến còn lại cũng sẽ bị ảnh hưởng>>> a[0] = 0 Do đó, các hoạt động gán bình thường thường được sử dụng khi chúng ta phải xử lý các loại đối tượng không thay đổi. Trong trường hợp này, khi một thao tác được thực hiện bằng bất kỳ biến nào trong hai biến, biến còn lại sẽ không thay đổi vì tham chiếu của nó đang trỏ tới đối tượng cũ cũng không thay đổi, với điều kiện là nó không thay đổi >>> a = 10 0
Bản sao nông vs Bản sao sâuTrước khi đi sâu vào chi tiết của các bản sao nông và sâu, hãy lưu ý rằng sự khác biệt của chúng chỉ liên quan khi chúng ta phải xử lý các đối tượng phức hợp về cơ bản là các cấu trúc lồng nhau. Nói cách khác, các đối tượng ghép là các đối tượng chứa các đối tượng khác — ví dụ: danh sách các danh sách hoặc từ điển các tập hợp Một bản sao nông sẽ lấy một bản sao của đối tượng ban đầu và tạo một đối tượng ghép mới nhưng nếu đối tượng chúng ta đang sao chép là một đối tượng ghép thì các đối tượng bên trong sẽ giống như các đối tượng được tìm thấy trong đối tượng ban đầu >>> a = 10 1Như chúng ta có thể thấy, các đối tượng danh sách >>> a = a + 1 8 và >>> list_1 = [1, 2, 3] 0 khác nhau, có nghĩa là chúng chứa các tham chiếu khác nhau trỏ đến các đối tượng khác nhau trong bộ nhớ (mặc dù giá trị của các đối tượng này giống nhau)Mọi thứ trở nên phức tạp hơn một chút khi chúng ta cần xử lý các đối tượng phức hợp. Bây giờ, hãy giả sử rằng biến >>> a = a + 1 8 là một đối tượng phức hợp đại diện cho một danh sách các danh sách>>> a = 10 5Bây giờ chúng tôi lấy một bản sao nông của >>> a = a + 1 8>>> a = 10 7và chúng ta có thể thấy rằng >>> a = a + 1 8 và >>> list_1 = [1, 2, 3] 0 là các đối tượng khác nhau>>> a = a + 1 0tuy nhiên, các đối tượng bên trong (i. e. hai danh sách bên trong) giống với danh sách được tham chiếu bởi đối tượng ban đầu >>> a = a + 1 1Điều này khá nguy hiểm vì sự thay đổi trong bất kỳ danh sách bên trong nào sẽ ảnh hưởng đến đối tượng phức hợp khác tham chiếu đến các danh sách bên trong này >>> a = a + 1 2Do đó, một bản sao nông chỉ phù hợp khi chúng ta không phải xử lý các đối tượng ghép
Một bản sao sâu sẽ lấy một bản sao của đối tượng ban đầu và sau đó sẽ sao chép đệ quy các đối tượng bên trong được tìm thấy (nếu có) >>> a = a + 1 3Một lần nữa, chúng ta có thể thấy rằng đối tượng gốc và đối tượng sao chép về cơ bản là khác nhau >>> a = a + 1 0nhưng trong trường hợp này, ngay cả các đối tượng bên trong cũng sẽ khác >>> a = a + 1 5Điều này có nghĩa là thay đổi trong bất kỳ danh sách lồng nhau nào trong >>> a = a + 1 8 sẽ không ảnh hưởng đến danh sách tương ứng trong đối tượng >>> list_1 = [1, 2, 3] 0>>> a = a + 1 6Do đó, một bản sao sâu sẽ phù hợp hơn khi chúng ta phải xử lý các đối tượng hỗn hợp và muốn đảm bảo rằng sự thay đổi trong bất kỳ đối tượng bên trong nào sẽ không ảnh hưởng đến các biến khác tham chiếu đến cùng một đối tượng
Sự kết luậnTrong bài viết này, chúng ta đã khám phá ba cách cơ bản mà một người có thể sử dụng để sao chép các đối tượng trong Python. Ban đầu, chúng tôi đã thảo luận về sự khác biệt giữa các loại đối tượng không thay đổi và có thể thay đổi. Không cần thiết phải sao chép các loại đối tượng bất biến vì giá trị của các trường hợp đó sẽ không bao giờ thay đổi. Mặt khác, các nhà phát triển cần cẩn thận khi sửa đổi các loại đối tượng có thể thay đổi vì hành động này có khả năng ảnh hưởng đến các biến khác đang giữ tham chiếu đến cùng một đối tượng. Khi đối tượng như vậy được thay đổi tại chỗ, thì tất cả các biến khác tham chiếu đến cùng một đối tượng cũng sẽ bị ảnh hưởng bởi thay đổi này Do đó, điều quan trọng là phải hiểu cách sao chép đúng các đối tượng có thể thay đổi để tránh các lỗi trong mã của bạn. Nhớ lại rằng một bản sao nông sẽ tạo ra một đối tượng mới từ bản gốc, tuy nhiên nếu đối tượng chứa các đối tượng khác thì các đối tượng bên trong sẽ không được sao chép mà thay vào đó, cùng một tham chiếu sẽ được sử dụng làm cấu trúc ban đầu. Mặt khác, một bản sao sâu sẽ tạo ra một đối tượng mới ngay cả đối với các đối tượng bên trong chứa trong một đối tượng phức hợp Bản sao Python có phải là bản sao sâu không?bản sao() 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 . Như bạn có thể thấy rằng cả hai đều có cùng giá trị nhưng có ID khác nhau.
Bản sao () nông hay sâu?Trong Bản sao nông, một bản sao của đối tượng ban đầu được lưu trữ và cuối cùng chỉ có địa chỉ tham chiếu được sao chép. Trong Bản sao sâu, cả bản sao của đối tượng gốc và bản sao lặp lại đều được lưu trữ. 2.
. Sao chép sâu Tại sao Python sao chép nông?Bản sao nông tạo đối tượng mới lưu trữ tham chiếu của các phần tử ban đầu . Vì vậy, một bản sao nông 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à, quá trình sao chép không lặp lại hoặc tự tạo bản sao của các đối tượng lồng nhau. |