Bản sao sâu của Python không hoạt động

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

Một bức tranh trị giá 1.000 từ. Hình ảnh của tác giả

sao chép hay không

Trong Python, bạn có thể sử dụng bản sao toán tử 

print[id[numbers]]
print[id[new_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

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]]
print[id[new_numbers]]
3 và 
print[id[numbers]]
print[id[new_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

Để 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]]
print[id[new_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[numbers]]
print[id[new_numbers]]
3 và 
print[id[numbers]]
print[id[new_numbers]]
4, bạn có thể thấy chúng hoàn toàn giống nhau

print[id[numbers]]
print[id[new_numbers]]

đầu ra

139804802851400
139804802851400

Đây là một minh họa hữu ích

Việc gán một đối tượng cho một biến mới sẽ tạo bí danh của đối tượng ban đầu. Hình ảnh của tác giả

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

  1. Bản sao nông
  2. Bản sao sâu

Cả hai phương pháp này đều được triển khai trong mô-đun 

print[id[numbers]]
print[id[new_numbers]]
8. Để sử dụng những thứ này, bạn cần nhập mô-đun 
print[id[numbers]]
print[id[new_numbers]]
8 vào dự án của mình

  • Để lấy một bản sao nông, hãy gọi 
    139804802851400
    139804802851400
    0
  • Để lấy một bản sao sâu, hãy gọi 
    139804802851400
    139804802851400
    1

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ó 

139804802851400
139804802851400
2, 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
139804802851400
3. Hãy kiểm tra những

  1. ID của 
    139804802851400
    139804802851400
    2 không giống với ID của 
    139804802851400
    139804802851400
    3, điều này là hợp lý vì 
    139804802851400
    139804802851400
    3 là bản sao của 
    139804802851400
    139804802851400
    2
numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
1

đầu ra

numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
2

Có vẻ như 

139804802851400
139804802851400
3 là một bản sao hoàn toàn độc lập của 
139804802851400
139804802851400
2. Nhưng hãy tiến thêm một bước để thấy rằng không phải

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 

139804802851400
139804802851400
3 bằng với ID của các danh sách trong 
139804802851400
139804802851400
2 gốc

numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
7

đầu ra

numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
8

Độ 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]
new_numbers: [100, 2, 3]
9

đầu ra

numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
0

3. Danh sách "bên ngoài" của 

139804802851400
139804802851400
3 là bản sao "thực" của bản gốc 
139804802851400
139804802851400
2. 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
139804802851400
2 ban đầu

Ví dụ: hãy thay thế danh sách đầu tiên trong 

139804802851400
139804802851400
3 bằng một chuỗi. Điều này sẽ không ảnh hưởng đến ____92

numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
1

đầu ra

numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
2

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]
new_numbers: [100, 2, 3]
3

Ở đây, bạn có 

139804802851400
139804802851400
2, 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
139804802851400
3. Hãy kiểm tra những

  1. ID của 
    139804802851400
    139804802851400
    2 và 
    139804802851400
    139804802851400
    3 không khớp
numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
1

đầu ra

numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
5

2. ID của các danh sách trong

139804802851400
139804802851400
3 không bằng ID của các danh sách trong 
139804802851400
139804802851400
2

numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
7

đầu ra

numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
7

Việc thay đổi một số trong 

139804802851400
139804802851400
3 không thay đổi giá trị đó trong 
139804802851400
139804802851400
2 ban đầu

numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
9

đầu ra

numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
9

3. _

139804802851400
139804802851400
3 là bản sao độc lập của 
139804802851400
139804802851400
2. Do đó, không có cách nào thay đổi được thực hiện trong
139804802851400
139804802851400
3 sẽ hiển thị trong bản gốc 
139804802851400
139804802851400
2

numbers: [100, 2, 3]
new_numbers: [100, 2, 3]
1

đầu ra

print[id[numbers]]
print[id[new_numbers]]
1

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ạ”

Danh sách Python có sao chép bản sao sâu không?

Bản sao Python. copy[] đã tạo một bản sao thực sự của danh sách gốc. Tuy nhiên, đó vẫn là một bản sao nông và các danh sách lồng nhau đề cập chính xác đến cùng một vị trí bộ nhớ. Nói cách khác, bản. copy[] chỉ tạo các bản sao cấp cao nhất và không sao chép các đối tượng lồng nhau.

Danh sách [] có tạo bản sao sâu không?

Bạn không tạo một bản sao sâu bằng list[] .

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

Bản sao sâu có làm chậm Python không?

deepcopy[] cực kỳ chậm . Lưu câu hỏi này. Hiển thị hoạt động trên bài đăng này. Tôi có một trạng thái trò chơi bằng Python với khoảng 1000 đối tượng [hệ hành tinh + sao + hành tinh] và tôi cần sao chép nó cũng như áp dụng một loạt các phép biến đổi cho nó khi được yêu cầu.

Chủ Đề