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
>>> print[a]
11
>>> print[b]
10
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

Các đối tượng không thể thay đổi so với có thể thay đổi

Trướ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 = a # variables a and b hold the reference to the same object

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
>>> print[a]
11
>>> print[b]
10
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
>>> print[a]
11
>>> print[b]
10

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]
>>> list_2 = list_1

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
>>> print[list_1]
[0, 2, 3]
>>> print[list_2]
[0, 2, 3]

Để 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 Python

là 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ường

Cá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]
b = a

Trong trường hợp này, cả hai biến

>>> a = a + 1
>>> print[a]
11
>>> print[b]
10
8 và
>>> list_1 = [1, 2, 3]
>>> list_2 = list_1
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
>>> print[a]
[0, 2, 3]
>>> print[b]
[0, 2, 3]

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
>>> b = a # variables a and b hold the reference to the same object
0

Câu lệnh gán trong Python không sao chép đối tượng, chúng tạo liên kết giữa mục tiêu và đối tượng — Python Docs

Bản sao nông vs Bản sao sâu

Trướ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
>>> b = a # variables a and b hold the reference to the same object
1

Như chúng ta có thể thấy, các đối tượng danh sách

>>> a = a + 1
>>> print[a]
11
>>> print[b]
10
8 và
>>> list_1 = [1, 2, 3]
>>> list_2 = list_1
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
>>> print[a]
11
>>> print[b]
10
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
>>> b = a # variables a and b hold the reference to the same object
5

Bây giờ chúng tôi lấy một bản sao nông của

>>> a = a + 1
>>> print[a]
11
>>> print[b]
10
8

>>> a = 10
>>> b = a # variables a and b hold the reference to the same object
7

và chúng ta có thể thấy rằng

>>> a = a + 1
>>> print[a]
11
>>> print[b]
10
8 và
>>> list_1 = [1, 2, 3]
>>> list_2 = list_1
0 là các đối tượng khác nhau

>>> a = a + 1
>>> print[a]
11
>>> print[b]
10
0

tuy 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
>>> print[a]
11
>>> print[b]
10
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
>>> print[a]
11
>>> print[b]
10
2

Do đó, 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 nông xây dựng một đối tượng phức hợp mới và sau đó [trong phạm vi có thể] chèn vào đó các tham chiếu đến các đối tượng được tìm thấy trong bản gốc — Tài liệu Python

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
>>> print[a]
11
>>> print[b]
10
3

Mộ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
>>> print[a]
11
>>> print[b]
10
0

như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
>>> print[a]
11
>>> print[b]
10
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
>>> print[a]
11
>>> print[b]
10
8 sẽ không ảnh hưởng đến danh sách tương ứng trong đối tượng
>>> list_1 = [1, 2, 3]
>>> list_2 = list_1
0

>>> a = a + 1
>>> print[a]
11
>>> print[b]
10
6

Do đó, 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

Một bản sao sâu xây dựng một đối tượng phức hợp mới và sau đó, theo cách đệ quy, chèn các bản sao của các đối tượng được tìm thấy trong bản gốc vào đó — Tài liệu Python

Sự kết luận

Trong 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.

Chủ Đề