Đối tượng nào không thể được sao chép trong python?

Bài viết này giải thích cách bạn có thể sao chép các đối tượng bất biến trong Python từ biến này sang biến khác bằng cách sử dụng phương pháp sao chép nông và sao chép sâu

Các đối tượng Python có thể là bất biến [số nguyên, float, bool, tuple, v.v. ] hoặc có thể thay đổi [danh sách, từ điển, bộ]. Vì không thể cập nhật các đối tượng bất biến nên việc sao chép chúng luôn sao chép vị trí bộ nhớ của chúng

Đối với các đối tượng có thể thay đổi, bạn có ba cách chính để sao chép chúng. sử dụng toán tử gán, sao chép nông một đối tượng hoặc sao chép sâu một đối tượng. Bạn sẽ nghiên cứu ba cách tiếp cận này trong hướng dẫn này

Sao chép qua Toán tử chuyển nhượng

Trước khi chúng tôi nghiên cứu sự khác biệt giữa sao chép nông và sao chép sâu các đối tượng Python, điều quan trọng là phải hiểu cách toán tử gán [=] gán giá trị cho các biến

Toán tử gán chỉ cần gán tham chiếu bộ nhớ của một đối tượng cho một đối tượng khác thay vì tạo các bản sao mới của các giá trị được lưu trữ bởi một biến. Hãy xem một ví dụ

Đoạn script sau định nghĩa một danh sách,num1 và gán biến danh sách này tonums2

nums1 = [10, 20, 30, 40, 50]

nums2 = nums1

print[nums2]
print[nums1]

đầu ra

[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]

Nếu bạn nhìn vào vị trí bộ nhớ của cả hai biến thenums1andnums2, bạn sẽ thấy rằng chúng trỏ đến vị trí bộ nhớ giống hệt nhau

print[hex[id[nums1]]]
print[hex[id[nums2]]]

đầu ra

0x1560e31c7c0
0x1560e31c7c0

Điều này có nghĩa là khi bạn cập nhật một giá trị trong bất kỳ biến nào trong hai biến danh sách, thay đổi đó sẽ được phản ánh trong danh sách kia. Ví dụ: nếu bạn gán giá trị 500 cho chỉ mục thứ hai của thenums2list, bạn sẽ nhận thấy rằng chỉ mục thứ hai của thenums1list cũng được cập nhật

nums2[2] = 500
print[nums2]
print[nums1]

đầu ra

[10, 20, 500, 40, 50]
[10, 20, 500, 40, 50]

Đây là một khái niệm quan trọng cần hiểu và bạn có thể chưa nhận ra

Nhận miễn phí Bộ công cụ dành cho nhà phát triển Python của chúng tôi

Tôi đã tập hợp Bộ công cụ dành cho nhà phát triển Python với hơn 100 tập lệnh Python được tạo sẵn bao gồm cấu trúc dữ liệu, Pandas, NumPy, Seaborn, máy học, xử lý tệp, quét web và nhiều thứ khác - và tôi muốn bạn có bộ công cụ này miễn phí. Nhập địa chỉ email của bạn dưới đây và tôi sẽ gửi một bản sao theo cách của bạn

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ể bị thay đổi 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

[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]
0

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ớ

[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]
1

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

[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]
2

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

>>> a = a + 1
>>> print[a]
11
>>> print[b]
10
8 và
[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]
00 đề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

[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]
5

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 hướng tới đối tượng cũ cũng không thay đổi, với điều kiện là nó không thay đổi

[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]
6

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

[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]
7

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à
[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]
00 khác nhau, 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

print[hex[id[nums1]]]
print[hex[id[nums2]]]
1

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

print[hex[id[nums1]]]
print[hex[id[nums2]]]
3

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

>>> a = a + 1
>>> print[a]
11
>>> print[b]
10
8 và
[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]
00 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 các tham chiếu vào đó tới 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
[10, 20, 30, 40, 50]
[10, 20, 30, 40, 50]
00

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

Phần 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 có thể sao chép một đối tượng trong Python không?

Sao chép các đối tượng Python tùy ý . copy. sao chép[] và sao chép. Các hàm deepcopy[] có thể được sử dụng để sao chép bất kỳ đối tượng nào.

Một đối tượng có thể được sao chép?

Các đối tượng được gán và sao chép theo tham chiếu . Nói cách khác, một biến lưu trữ không phải “giá trị đối tượng”, mà là “tham chiếu” [địa chỉ trong bộ nhớ] cho giá trị. Vì vậy, sao chép một biến như vậy hoặc chuyển nó dưới dạng đối số hàm sao chép tham chiếu đó, chứ không phải chính đối tượng đó.

Làm cách nào bạn có thể sao chép các mục trong Python?

Sao chép đối tượng trong Python . Bạn có thể nghĩ rằng điều này tạo ra một đối tượng mới; . Nó chỉ tạo một biến mới chia sẻ tham chiếu của đối tượng ban đầu. use = operator to create a copy of an object. You may think that this creates a new object; it doesn't. It only creates a new variable that shares the reference of the original object.

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.

Chủ Đề