Sao chép hoặc tham khảo bài tập python

Đầu tiên mình mô tả một chút về quản lý và tối ưu bộ nhớ trong Python. Sau khi đặt nền tảng, tôi giải thích sự khác biệt giữa câu lệnh gán, bản sao nông và bản sao sâu. Sau đó tôi tóm tắt sự khác biệt trong một bảng

Nếu bạn thích xem video hơn là đọc một bài viết, bạn có thể tìm thấy video bổ sung tại đây

Quản lý bộ nhớ trong Python

int, float, list, dict, class instance,… chúng đều là đối tượng trong Python. Trong quá trình triển khai CPython, hàm tích hợp sẵn

>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
3 trả về địa chỉ bộ nhớ của một đối tượng —

>>> L1 = [1, 2, 3]>>> id[L1]
3061530120

Nếu chúng ta tạo một biến mới

>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
4 tham chiếu đến một đối tượng có cùng giá trị với
>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
5, thì
>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
4 sẽ có một địa chỉ bộ nhớ mới —

>>> L2 = [1, 2, 3]>>> id[L2]
3061527304

Mỗi khi một đối tượng mới được tạo, nó sẽ có một địa chỉ bộ nhớ mới. Ngoại trừ khi nó là -

  1. một chuỗi rất ngắn
  2. một số nguyên trong [-5, 256]
  3. một thùng chứa bất biến rỗng [e. g. bộ dữ liệu]

Hãy xem một ví dụ với một đối tượng số nguyên. Cả

>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
7 và
>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
8 đều đề cập đến cùng một giá trị 10. Trong khi
>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
5 và
>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
4 trong ví dụ trước có hai địa chỉ bộ nhớ khác nhau, thì
>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
7 và
>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
8 chia sẻ cùng một địa chỉ bộ nhớ —

>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
2

Đó là bởi vì, trong ba trường hợp ngoại lệ đó, Python tối ưu hóa bộ nhớ bằng cách để biến thứ hai tham chiếu đến cùng một đối tượng trong bộ nhớ, — một số người gọi nó là “đối tượng được chia sẻ”

Hãy ghi nhớ khái niệm về đối tượng được chia sẻ vì chúng ta sẽ cần đến nó sau này khi chúng ta tạo một bản sao sâu của một đối tượng

Chuyển nhượng biến

Nó nói trong tài liệu Python rằng “Các câu lệnh gán trong Python không sao chép các đối tượng, chúng tạo ra các liên kết giữa một mục tiêu và một đối tượng. ” Điều đó có nghĩa là khi chúng ta tạo một biến bằng cách gán, biến mới đề cập đến cùng một đối tượng như biến ban đầu —

>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
3

Bởi vì biến mới

>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
3 và biến ban đầu
>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
4 chia sẻ cùng một đối tượng [i. e. cùng một danh sách], chúng cũng chứa các phần tử giống nhau —

>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
6

Như minh họa trong hình bên dưới,

>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
4 và
>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
3 chia sẻ cùng một
>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
7, i. e. , chúng tham chiếu đến cùng một đối tượng trong bộ nhớ. Và chúng cũng chứa các yếu tố giống nhau

Bản sao nông

Khi chúng ta tạo một biến bằng bản sao nông, biến mới đề cập đến một đối tượng mới —

>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
0

Mặc dù

>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
4 và
>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
9 đề cập đến hai đối tượng khác nhau [i. e. hai danh sách có địa chỉ bộ nhớ khác nhau], các phần tử trong hai danh sách đề cập đến cùng một đối tượng —

>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
3

Hình bên dưới minh họa cách các phần tử trong

>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
4 đề cập đến các đối tượng giống như các phần tử trong
>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
9

Sao chép sâu

Tương tự như sao chép nông, khi chúng ta tạo một biến bằng cách sao chép sâu, biến mới tham chiếu đến một đối tượng mới —

>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
6

Như được mô tả trong tài liệu Python —

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

- 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 tới các đối tượng được tìm thấy trong bản gốc

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

Vì vậy, khác với bản sao nông, các phần tử trong hai danh sách hiện đề cập đến các đối tượng khác nhau -

>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
7

Nhưng tại sao

>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
22 và
>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
23 chia sẻ cùng một đối tượng [tôi. e. có cùng địa chỉ bộ nhớ]?

Hình dưới đây cho thấy

>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
4 và
>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
25 đề cập đến hai danh sách khác nhau trong bộ nhớ và các phần tử trong
>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
4 đề cập đến các đối tượng khác với các phần tử trong
>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
25 ngoại trừ các phần tử số nguyên do tối ưu hóa bộ nhớ

Bản tóm tắt

Nếu có một điểm rút ra từ bài viết này, thì đó phải là bảng dưới đây. Phép gán biến không sao chép các đối tượng, vì vậy

>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
4 và
>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
3 có cùng địa chỉ bộ nhớ và chứa các phần tử giống nhau. Bản sao nông tạo một đối tượng mới cho
>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
9, nhưng các phần tử trong
>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
9 vẫn tham chiếu đến các đối tượng giống như các phần tử trong
>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
4. Bản sao sâu cũng tạo đối tượng mới cho
>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
25 và các phần tử trong
>>> L1 = [1, 2, 3]>>> id[L1]
3061530120
25 đề cập đến các đối tượng khác với các phần tử đó trong
>>> L2 = [1, 2, 3]>>> id[L2]
3061527304
4 với ba loại ngoại lệ

Bài tập Python có phải là bản sao hoặc tài liệu tham khảo không?

Trong Python, Các câu lệnh gán không sao chép các đối tượng , chúng tạo ra các ràng buộc giữa mục tiêu và đối tượng. Khi chúng ta sử dụng toán tử =, Nó chỉ tạo một biến mới chia sẻ tham chiếu của đối tượng ban đầu.

Bài tập có tạo một bản sao trong Python không?

Các câu lệnh gán trong Python không sao chép các đối tượng , chúng tạo ra các ràng buộc giữa mục tiêu và đối tượng. Đối với các bộ sưu tập có thể thay đổi hoặc chứa các mục có thể thay đổi, đôi khi cần có một bản sao để một người có thể thay đổi một bản sao mà không cần thay đổi bản kia.

Bài tập Python có phải là bản sao sâu không?

Sử dụng phép gán = nếu bạn muốn những thay đổi mới ảnh hưởng đến danh sách ban đầu. Sử dụng bản sao sâu nếu bạn không muốn những thay đổi mới ảnh hưởng đến danh sách ban đầu . Nhớ lại. bản sao sâu đảm bảo rằng đối tượng mới được sao chép không được tham chiếu đến đối tượng ban đầu theo bất kỳ cách nào.

Python có sao chép danh sách khi được giao không?

Tóm lại, toán tử gán [=] tạo một tham chiếu mới tới một đối tượng trong bộ nhớ. Nó không sao chép bất cứ thứ gì . Điều này áp dụng cho danh sách cũng như bất kỳ đối tượng nào khác trong Python.

Chủ Đề