Trong Python, bản sao nông là bản sao “sâu một cấp độ”. Đối tượng được sao chép chứa tham chiếu đến đối tượng con của đối tượng ban đầu
Một bản sao sâu hoàn toàn độc lập với đối tượng ban đầu. Nó xây dựng một đối tượng bộ sưu tập mới bằng cách điền đệ quy nó với các bản sao của các đối tượng con
sao chép hay không
Trong Python, bạn có thể sử dụng bản sao toán tử
print[id[numbers]]2 của một đối tượng. Thật hấp dẫn khi nghĩ rằng điều này tạo ra một đối tượng mới, nhưng nó không. Thay vào đó, nó tạo một biến mới tham chiếu đến đối tượng ban đầu. Điều này có nghĩa là thay đổi một giá trị trong đối tượng được sao chép cũng sẽ thay đổi giá trị của đối tượng ban đầu
print[id[new_numbers]]
Hãy sử dụng danh sách để chứng minh điều này
numbers = [1, 2, 3] new_numbers = numbers new_numbers[0] = 100 print['numbers: ', numbers] print['new_numbers: ', new_numbers]
đầu ra
numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
Vì
print[id[numbers]]3 và
print[id[new_numbers]]
print[id[numbers]]4 hiện trỏ đến cùng một danh sách nên việc cập nhật danh sách này luôn cập nhật danh sách kia
print[id[new_numbers]]
Để xác minh rằng cả hai đối tượng thực sự tham chiếu đến cùng một đối tượng, bạn cũng có thể sử dụng phương thức
print[id[numbers]]5 . Mỗi đối tượng Python có một ID duy nhất. Nếu kiểm tra ID của
print[id[new_numbers]]
print[id[numbers]]3 và
print[id[new_numbers]]
print[id[numbers]]4, bạn có thể thấy chúng hoàn toàn giống nhau
print[id[new_numbers]]
print[id[numbers]]
print[id[new_numbers]]
đầu ra
139804802851400
139804802851400
Đây là một minh họa hữu ích
Cách sao chép bằng Python
Hãy đi qua một ví dụ phổ biến. Bạn muốn sao chép một danh sách sao cho danh sách ban đầu không bị thay đổi khi cập nhật danh sách đã sao chép. Có hai cách để sao chép trong Python
- Bản sao nông
- Bản sao sâu
Cả hai phương pháp này đều được triển khai trong mô-đun
print[id[numbers]]8. Để sử dụng những thứ này, bạn cần nhập mô-đun
print[id[new_numbers]]
print[id[numbers]]8 vào dự án của mình
print[id[new_numbers]]
- Để lấy một bản sao nông, hãy gọi
139804802851400
0
139804802851400 - Để lấy một bản sao sâu, hãy gọi
139804802851400
1
139804802851400
Hãy tìm hiểu sâu hơn về các chi tiết
Sao chép nông vs. Sao chép sâu
Bản sao nông
Bản sao nông là nông vì nó chỉ sao chép đối tượng chứ không sao chép các đối tượng con của nó. Thay vào đó, các đối tượng con tham chiếu đến các đối tượng con của đối tượng ban đầu
Điều này có thể được chứng minh bằng ví dụ sau
numbers = [1, 2, 3] new_numbers = numbers new_numbers[0] = 100 print['numbers: ', numbers] print['new_numbers: ', new_numbers]4
Ở đây, bạn có
1398048028514002, là một danh sách gồm các số. Và bạn có một bản sao sơ sài có tên là
139804802851400
1398048028514003. Hãy kiểm tra những
139804802851400
- ID của
139804802851400
2 không giống với ID của
139804802851400139804802851400
3, điều này là hợp lý vì
139804802851400139804802851400
3 là bản sao của
139804802851400139804802851400
2
139804802851400
numbers: [100, 2, 3]1
new_numbers: [100, 2, 3]
đầu ra
numbers: [100, 2, 3]2
new_numbers: [100, 2, 3]
Có vẻ như
1398048028514003 là một bản sao hoàn toàn độc lập của
139804802851400
1398048028514002. Nhưng hãy tiến thêm một bước để thấy rằng không phải
139804802851400
2. Đây là nơi mà sự nông cạn trở nên rõ ràng. ID của các danh sách trong
1398048028514003 bằng với ID của các danh sách trong
139804802851400
1398048028514002 gốc
139804802851400
numbers: [100, 2, 3]7
new_numbers: [100, 2, 3]
đầu ra
numbers: [100, 2, 3]8
new_numbers: [100, 2, 3]
Độ nông có nghĩa là chỉ danh sách “bên ngoài” được sao chép. Nhưng danh sách bên trong vẫn đề cập đến danh sách của danh sách gốc. Do đó, việc thay đổi một số trong danh sách đã sao chép sẽ ảnh hưởng đến danh sách gốc
numbers: [100, 2, 3]9
new_numbers: [100, 2, 3]
đầu ra
numbers: [100, 2, 3]0
new_numbers: [100, 2, 3]
3. Danh sách "bên ngoài" của
1398048028514003 là bản sao "thực" của bản gốc
139804802851400
1398048028514002. Do đó, bạn có thể thêm các phần tử mới vào nó hoặc thậm chí thay thế các phần tử hiện có. Những thay đổi này sẽ không ảnh hưởng đến danh sách
139804802851400
1398048028514002 ban đầu
139804802851400
Ví dụ: hãy thay thế danh sách đầu tiên trong
1398048028514003 bằng một chuỗi. Điều này sẽ không ảnh hưởng đến ____92
139804802851400
numbers: [100, 2, 3]1
new_numbers: [100, 2, 3]
đầu ra
numbers: [100, 2, 3]2
new_numbers: [100, 2, 3]
Bản sao sâu
Một bản sao sâu tạo ra một bản sao hoàn toàn độc lập của đối tượng ban đầu
Việc này thật thẳng thắn. Nhưng để hoàn thiện, hãy lặp lại các thí nghiệm trên với một bản sao sâu
numbers: [100, 2, 3]3
new_numbers: [100, 2, 3]
Ở đây, bạn có
1398048028514002, là một danh sách chứa danh sách các số. Và bạn có một bản sao sâu,
139804802851400
1398048028514003. Hãy kiểm tra những
139804802851400
- ID của
139804802851400
2 và
139804802851400139804802851400
3 không khớp
139804802851400
numbers: [100, 2, 3]1
new_numbers: [100, 2, 3]
đầu ra
numbers: [100, 2, 3]5
new_numbers: [100, 2, 3]
2. ID của các danh sách trong
1398048028514003 không bằng ID của các danh sách trong
139804802851400
1398048028514002
139804802851400
numbers: [100, 2, 3]7
new_numbers: [100, 2, 3]
đầu ra
numbers: [100, 2, 3]7
new_numbers: [100, 2, 3]
Việc thay đổi một số trong
1398048028514003 không thay đổi giá trị đó trong
139804802851400
1398048028514002 ban đầu
139804802851400
numbers: [100, 2, 3]9
new_numbers: [100, 2, 3]
đầu ra
numbers: [100, 2, 3]9
new_numbers: [100, 2, 3]
3. _
1398048028514003 là bản sao độc lập của
139804802851400
1398048028514002. Do đó, không có cách nào thay đổi được thực hiện trong
139804802851400
1398048028514003 sẽ hiển thị trong bản gốc
139804802851400
1398048028514002
139804802851400
numbers: [100, 2, 3]1
new_numbers: [100, 2, 3]
đầu ra
print[id[numbers]]1
print[id[new_numbers]]
Sự kết luận
Hôm nay bạn đã học được sự khác biệt giữa bản sao nông và bản sao sâu trong Python là gì
Bản sao nông là bản sao “sâu một cấp độ”. Nó xây dựng một đối tượng được sao chép. Nhưng các đối tượng con đề cập đến các đối tượng con của đối tượng ban đầu. Vì vậy, thoạt nghe có vẻ hơi “lạ”