Deepcopy() trong Python là gì?

Trong chương này, chúng tôi sẽ đề cập đến câu hỏi làm thế nào để sao chép danh sách và danh sách lồng nhau. Các vấn đề mà chúng ta sẽ gặp phải là các vấn đề chung của các kiểu dữ liệu có thể thay đổi. Cố gắng sao chép danh sách có thể là một trải nghiệm khó khăn đối với người mới. Nhưng trước đó, chúng tôi muốn tóm tắt một số hiểu biết từ chương trước "Kiểu dữ liệu và biến". Python thậm chí còn thể hiện một hành vi lạ đối với người mới bắt đầu sử dụng ngôn ngữ này - so với một số ngôn ngữ lập trình truyền thống khác - khi gán và sao chép các loại dữ liệu đơn giản như số nguyên và chuỗi. Sự khác biệt giữa sao chép nông và sâu chỉ liên quan đến các đối tượng phức hợp, tôi. e. các đối tượng chứa các đối tượng khác, như danh sách hoặc thể hiện của lớp

Trong đoạn mã sau, y trỏ đến cùng một vị trí bộ nhớ với X. Chúng ta có thể thấy điều này bằng cách áp dụng hàm id() trên x và y. Tuy nhiên, không giống như các con trỏ "thực" như trong C và C++, mọi thứ sẽ thay đổi khi chúng ta gán một giá trị mới cho y. Trong trường hợp này, y sẽ nhận một vị trí bộ nhớ riêng, như chúng ta đã thấy trong chương "Kiểu dữ liệu và biến" và có thể thấy trong ví dụ sau

x = 3
y = x
print(id(x), id(y)) 

ĐẦU RA

94400598764928 94400598764928

y = 4
print(id(x), id(y))

ĐẦU RA

94400598764928 94400598764960

print(x,y)

ĐẦU RA

3 4

Nhưng ngay cả khi hành vi bên trong này có vẻ lạ so với các ngôn ngữ lập trình như C, C++, Perl hay Java, kết quả có thể quan sát được của các nhiệm vụ trước đó là những gì chúng tôi đã dự đoán. e. nếu bạn không nhìn vào các giá trị id. Tuy nhiên, có thể có vấn đề nếu chúng ta sao chép các đối tượng có thể thay đổi như danh sách và từ điển

Python chỉ tạo các bản sao thực, nếu phải, tôi. e. nếu người dùng, lập trình viên, yêu cầu nó một cách rõ ràng

Chúng tôi sẽ giới thiệu cho bạn những vấn đề quan trọng nhất, có thể xảy ra khi sao chép các đối tượng có thể thay đổi như danh sách và từ điển

Đào tạo Python trực tiếp

Deepcopy() trong Python là gì?

Thưởng thức trang này?

Nhìn thấy. Tổng quan về các khóa học Python trực tiếp

đăng ký tại đây

Các biến chia sẻ một đối tượng

Bạn đang ở trang này để tìm hiểu về cách sao chép các đối tượng, đặc biệt là các danh sách. Tuy nhiên, bạn cần rèn luyện tính kiên nhẫn. Chúng tôi muốn hiển thị thứ gì đó trông giống như một bản sao cho nhiều người mới bắt đầu nhưng không liên quan gì đến các bản sao

colours1 = ["red", "blue"]
colours2 = colours1
print(colours1, colours2)

ĐẦU RA

['red', 'blue'] ['red', 'blue']

Cả hai biến tham chiếu cùng một đối tượng danh sách. Nếu chúng ta nhìn vào danh tính của các biến

print(x,y)
0 và
print(x,y)
1, chúng ta có thể thấy rằng cả hai đều là tham chiếu đến cùng một đối tượng

94400598764928 94400598764928
0

ĐẦU RA

94400598764928 94400598764928
1

Trong ví dụ trên, một danh sách đơn giản được gán cho colors1. Danh sách này được gọi là "danh sách nông", bởi vì nó không có cấu trúc lồng nhau, tôi. e. không có danh sách con nào được chứa trong danh sách. Trong bước tiếp theo, chúng tôi gán màu1 cho màu2

Hàm id() cho chúng ta thấy rằng cả hai biến đều trỏ đến cùng một đối tượng danh sách, i. e. họ chia sẻ đối tượng này

Deepcopy() trong Python là gì?

Chúng tôi có hai tên biến

print(x,y)
0 và
print(x,y)
1, mà chúng tôi đã mô tả dưới dạng hình bầu dục màu vàng. Hộp màu xanh tượng trưng cho đối tượng danh sách. Một đối tượng danh sách bao gồm các tham chiếu đến các đối tượng khác. Trong ví dụ của chúng tôi, đối tượng danh sách, được tham chiếu bởi cả hai biến, tham chiếu đến hai đối tượng chuỗi, i. e. "đỏ và xanh". Bây giờ chúng ta phải kiểm tra, điều gì sẽ xảy ra, nếu chúng ta chỉ thay đổi một phần tử của danh sách
print(x,y)
1 hoặc
print(x,y)
0

Bây giờ chúng ta muốn xem điều gì sẽ xảy ra nếu chúng ta gán một đối tượng mới cho

print(x,y)
1. Như mong đợi, các giá trị của
print(x,y)
0 không thay đổi. Giống như trong ví dụ của chúng tôi trong chương "Kiểu dữ liệu và biến", một vị trí bộ nhớ mới đã được phân bổ cho
print(x,y)
1, vì chúng tôi đã chỉ định một danh sách hoàn toàn mới, tôi. e. một đối tượng danh sách mới cho biến này

94400598764928 94400598764928
0

ĐẦU RA

94400598764928 94400598764928
1

94400598764928 94400598764928
2

ĐẦU RA

94400598764928 94400598764928
3

94400598764928 94400598764928
4

ĐẦU RA

94400598764928 94400598764928
3

94400598764928 94400598764928
6

ĐẦU RA

94400598764928 94400598764928
7

Chúng tôi đã gán một đối tượng mới cho biến 'colors2'. Trong đoạn mã sau, chúng tôi sẽ thay đổi đối tượng danh sách bên trong bằng cách gán một giá trị mới cho phần tử thứ hai của danh sách

94400598764928 94400598764928
8

Deepcopy() trong Python là gì?

Hãy xem, những gì đã xảy ra chi tiết trong đoạn mã trước. Chúng tôi đã gán một giá trị mới cho phần tử thứ hai của colors2, i. e. phần tử có chỉ số 1. Nhiều người mới bắt đầu sẽ ngạc nhiên vì danh sách màu1 cũng được "tự động" thay đổi. Tất nhiên, chúng tôi không có hai danh sách. Chúng tôi chỉ có hai tên cho cùng một danh sách

Giải thích là chúng ta đã không gán một đối tượng mới cho biến

print(x,y)
1. Chúng tôi đã thay đổi đối tượng được tham chiếu bởi
print(x,y)
1 trong nội bộ hoặc vì nó thường được gọi là "tại chỗ". Cả hai biến
print(x,y)
0 và
print(x,y)
1 vẫn trỏ đến cùng một đối tượng danh sách

Sao chép danh sách

Cuối cùng chúng ta đã đến chủ đề sao chép danh sách. Lớp

3 4
3 cung cấp phương thức
3 4
4 cho mục đích này. Mặc dù tên có vẻ rõ ràng, con đường này cũng có một điểm thu hút

Có thể thấy được lợi ích nếu chúng ta sử dụng trợ giúp trên

3 4
4

94400598764928 94400598764928
9

ĐẦU RA

y = 4
print(id(x), id(y))
0

Nhiều người mới bắt đầu bỏ qua từ "nông cạn" ở đây.

3 4
6 cho chúng ta biết rằng một danh sách mới sẽ được tạo bằng phương thức
3 4
4. Danh sách mới này sẽ là bản sao 'nông' của danh sách gốc

Về nguyên tắc, từ "nông" là không cần thiết hoặc thậm chí gây hiểu nhầm trong định nghĩa này

Trước tiên, bạn nên nhớ danh sách trong Python là gì. Một danh sách trong Python là một đối tượng bao gồm một chuỗi tham chiếu đến các đối tượng Python. Sau đây là danh sách các chuỗi

Deepcopy() trong Python là gì?

Danh sách mà biến

3 4
8 đang tham chiếu là danh sách các chuỗi. Về cơ bản, đối tượng danh sách chỉ là hộp màu xanh với các mũi tên, tôi. e. các tham chiếu đến các chuỗi. Bản thân các chuỗi không phải là một phần của danh sách

y = 4
print(id(x), id(y))
1

Ví dụ trước danh sách tên

3 4
8 là đồng nhất, tôi. e. nó chỉ bao gồm các chuỗi, vì vậy tất cả các phần tử có cùng kiểu dữ liệu. Nhưng bạn nên lưu ý rằng các tham chiếu của một danh sách có thể tham chiếu đến bất kỳ đối tượng nào. Danh sách sau đây
colours1 = ["red", "blue"]
colours2 = colours1
print(colours1, colours2)
0 là một danh sách tổng quát hơn

Deepcopy() trong Python là gì?

y = 4
print(id(x), id(y))
2

Khi một danh sách được sao chép, chúng tôi sao chép các tài liệu tham khảo. Trong ví dụ của chúng tôi, đây là những hộp màu xanh được tham chiếu bởi

3 4
8 và bởi
colours1 = ["red", "blue"]
colours2 = colours1
print(colours1, colours2)
0. Ý nghĩa của điều này được thể hiện trong chương phụ sau đây

Đào tạo Python trực tiếp

Deepcopy() trong Python là gì?

Thưởng thức trang này?

Nhìn thấy. Tổng quan về các khóa học Python trực tiếp

Các khóa học trực tuyến sắp tới

Khái niệm cơ bản về Python cho người mới bắt đầu

Khóa học nâng cao chuyên sâu

Python dành cho kỹ sư và nhà khoa học

Lập trình hướng đối tượng với Python

đăng ký tại đây

Các vấn đề về sao chép danh sách

Sao chép danh sách có thể dễ dàng bị hiểu lầm và sự hiểu lầm này có thể dẫn đến những lỗi khó chịu. Chúng tôi sẽ trình bày điều này dưới dạng một câu chuyện tình yêu hơi khác

Deepcopy() trong Python là gì?

Hãy tưởng tượng một người sống ở thành phố Constance. Thành phố nằm ở miền Nam nước Đức bên bờ hồ Constance (Bodensee trong tiếng Đức). Sông Rhine, bắt nguồn từ dãy núi Alps của Thụy Sĩ, chảy qua Hồ Constance và rời khỏi nó, lớn hơn đáng kể. Người này tên là Swen sống ở "Seestrasse", một trong những con phố đắt đỏ nhất của Constance. Căn hộ của anh có hướng nhìn thẳng ra hồ và thành phố Constance. Chúng tôi đặt một số thông tin về Swen trong cấu trúc danh sách sau đây

y = 4
print(id(x), id(y))
3

Deepcopy() trong Python là gì?

Một ngày đẹp trời, Sarah xinh đẹp gặp Swen, Hoàng tử quyến rũ của cô. Để cắt ngắn câu chuyện. Yêu từ cái nhìn đầu tiên và cô ấy chuyển đến sống với Swen

Bây giờ, việc tạo tập dữ liệu cho Sarah là tùy thuộc vào chúng tôi. Chúng tôi lười biếng và chúng tôi sẽ tái chế dữ liệu của Swen, vì cô ấy sẽ sống với anh ấy trong cùng một căn hộ

Chúng tôi sẽ sao chép dữ liệu của Swen và đổi tên thành Sarah

y = 4
print(id(x), id(y))
4

ĐẦU RA

y = 4
print(id(x), id(y))
5

Deepcopy() trong Python là gì?

Họ sống rất hòa thuận và yêu thương sâu sắc trong một thời gian dài, chẳng hạn như cả một ngày cuối tuần. Cô chợt nhận ra rằng Swen là một con quái vật. Anh ấy nhuộm bơ bằng mứt cam và mật ong và thậm chí tệ hơn, anh ấy trải đôi tất đã mòn của mình trong phòng ngủ. Cô ấy không mất nhiều thời gian để đưa ra quyết định quan trọng. Cô sẽ rời xa anh và căn hộ mơ ước

Cô chuyển đến một con phố tên là Bücklestrasse. Một khu dân cư không nơi nào tốt đẹp bằng, nhưng ít nhất cô ấy đã tránh xa con quái vật

Làm thế nào chúng ta có thể sắp xếp bước đi này từ quan điểm của Python?

Đường phố có thể được truy cập bằng

colours1 = ["red", "blue"]
colours2 = colours1
print(colours1, colours2)
3. Vì vậy, chúng tôi đặt vị trí này ở vị trí mới

y = 4
print(id(x), id(y))
6

Chúng ta có thể thấy rằng Sarah đã di chuyển thành công đến vị trí mới

y = 4
print(id(x), id(y))
7

ĐẦU RA

y = 4
print(id(x), id(y))
8

Đây có phải là kết thúc của câu chuyện của chúng tôi?

y = 4
print(id(x), id(y))
9

ĐẦU RA

94400598764928 94400598764960
0

Swen là bám. Cô không thể thoát khỏi anh ta. Điều này có thể khá ngạc nhiên đối với một số. Tại sao nó như thế này? . Một đối tượng chuỗi ("Swen") và đối tượng kia vào danh sách lồng nhau (địa chỉ

colours1 = ["red", "blue"]
colours2 = colours1
print(colours1, colours2)
5. Khi chúng tôi sử dụng
3 4
4, chúng tôi chỉ sao chép những tài liệu tham khảo này. Điều này có nghĩa là cả
colours1 = ["red", "blue"]
colours2 = colours1
print(colours1, colours2)
7 và
colours1 = ["red", "blue"]
colours2 = colours1
print(colours1, colours2)
8 đều tham chiếu đến cùng một đối tượng danh sách. Khi chúng tôi thay đổi danh sách lồng nhau này, nó sẽ hiển thị trong cả hai danh sách

Deepcopy() trong Python là gì?

bản sao sâu từ bản sao Mô-đun

Một giải pháp cho vấn đề được mô tả được cung cấp bởi mô-đun

3 4
4. Mô-đun này cung cấp phương thức "deepcopy", cho phép sao chép toàn bộ hoặc sâu một danh sách tùy ý, tôi. e. nông và các danh sách khác

Hãy làm lại ví dụ trước với hàm

['red', 'blue'] ['red', 'blue']
0

94400598764928 94400598764960
1

Sau này, cấu trúc thực hiện trông như thế này

Deepcopy() trong Python là gì?

Chúng ta có thể thấy rằng danh sách lồng nhau có địa chỉ cũng đã được sao chép

Chúng ta có thể thấy bằng cách sử dụng hàm id rằng các danh sách con đã được sao chép, vì

['red', 'blue'] ['red', 'blue']
1 khác với
['red', 'blue'] ['red', 'blue']
2

94400598764928 94400598764960
2

ĐẦU RA

94400598764928 94400598764960
3

Một sự thật thú vị là các chuỗi không được sao chép. Chúng ta có thể thấy điều này nếu chúng ta xem ví dụ ở tên

['red', 'blue'] ['red', 'blue']
3 và
['red', 'blue'] ['red', 'blue']
4. Họ tham chiếu cùng một chuỗi

94400598764928 94400598764960
4

ĐẦU RA

94400598764928 94400598764960
5

Chúng tôi đã sao chép toàn bộ dữ liệu từ Swen. Vì vậy, tên của người2 vẫn là Sarah. Chúng ta phải đổi nó thành Sarah

94400598764928 94400598764960
6

Bây giờ nó trông như thế này trong nội bộ, tôi. e. Sarah và Swen sống cùng nhau

Deepcopy() trong Python là gì?

Vì Sarah đã chuyển đến, chúng tôi hiện đã chuẩn bị kỹ lưỡng cho hành động trốn chạy của cô ấy

Bây giờ, đã đến lúc Sara dọn ra ở riêng.

94400598764928 94400598764960
7

Cô ấy đã chuyển đi thành công và rời bỏ Swen mãi mãi, như chúng ta có thể thấy trong phần sau

94400598764928 94400598764960
8

ĐẦU RA

94400598764928 94400598764960
9

Để rõ ràng, chúng tôi cũng cung cấp một sơ đồ bao gồm tất cả những thay đổi chúng tôi đã thực hiện sau khi sao chép sâu

Chức năng Deepcopy là gì?

Deep copy trong Python là gì? . Nó có nghĩa là đầu tiên xây dựng một đối tượng bộ sưu tập mới và sau đó điền đệ quy nó với các bản sao của các đối tượng con được tìm thấy trong bản gốc. creates a new compound object before inserting copies of the items found in the original into it in a recursive manner. It means first constructing a new collection object and then recursively populating it with copies of the child objects found in the original.

Sự khác biệt giữa sao chép copy() và sao chép Deepcopy() là gì?

copy() tạo tham chiếu đến đối tượng ban đầu. Nếu bạn thay đổi đối tượng đã sao chép - bạn thay đổi đối tượng ban đầu. . deepcopy() tạo đối tượng mới và sao chép thực sự đối tượng gốc sang đối tượng mới. Thay đổi đối tượng được sao chép sâu mới không ảnh hưởng đến đối tượng gốc

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

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() .