Giải đáp thắc mắc về Variable và bộ nhớ trong Python

Tram Ho

Mở Đầu

Đầu tiên phải nói rằng mình đã có rất nhiều câu hỏi về bộ nhớ, biến được lưu trữ trong Python. Đôi khi nó làm mình cảm thấy không hiểu gì và không rành mạch hơn các ngôn ngữ trước đây mình từng tìm hiểu như C hay Java.
Do đó khi gặp các câu hỏi này lần đầu, mình đã chạy code trên máy cho chắc ăn, xem nó như thế nào (Chứ không dám chạy code trong đầu ) , dùng các trang để visualize để có thể hiều thêm về cách chạy , lưu chữ của chúng. Bắt đầu thôi.

Câu số 1: Copy một list trong Python

Câu hỏi này gần như có ở tất cả các bài Test về Python .

List b sẽ ra sao trong tình huống này ?


CÂU TRẢ LỜI LÀ : b SẼ KHÔNG THAY ĐỔI !
Giải thích : deepcopy(sao chép sâu) có nghĩa là nó tạo ra một bản sao đối tượng, chèn các đối tượng được tìm thấy trong bản gốc vào nó !
Do đó có bất kỳ thay đổi ở đối tượng ban đầu như thế nào cũng sẽ không ảnh hưởng đến đối tượng được hình thành sau khi copy (ở đây là b).

Đây là câu trả lời

Hình trên mô tả rất rõ ràng về DEEP COPY.

Nhân tiện câu hỏi này, mình xin bổ sung thêm về SHALLOW COPY


Giải thích về cách làm việc của Shallow copy : xây dựng một đối tượng mới sau đó chèn vào nó các tham chiếu cho các đối tượng được tìm thấy trong bản gốc.

Hình ảnh trên đã rõ câu trả lời )

Một lưu ý hết sức quan trọng : SỰ KHÁC BIỆT GIỮA SAO CHÉP NÔNG VÀ SÂU CHỈ KHI CÓ SỰ LIÊN QUAN ĐẾN CÁC ĐỐI TƯỢNG GHÉP (ĐỐI TƯỢNG CHỨA ĐỐI TƯỢNG) NHƯ DANH SÁCH … HAY CLASS INSTANCES-

Cụ thể là phần list con trong list cha như ví dụ trên a[2] : ['CR7', 'Messi']


Còn nếu như ví dụ ở dưới đây thì sự khác biệt là không có nhé :


Câu số 2: Liên quan đến gán trong Python

Câu hỏi :


Đáp án sẽ là : Cả a và b đều có kết quả là : [1, 2, 3, ‘日本語’, ‘English’] .

Giải thích : Tưởng rằng b sẽ tạo ra một danh sách riêng biệt: a, b có thể thay đổi tùy ý và độc lập. Nhưng không , thay đổi ở cả 2 đều tác động lên nhau.

Về mặt bộ nhớ : Khi gán một biến (a = [1,2,3] ), chúng ta chỉ nó đến một địa chỉ ô nhớ. Khi đó a là một dạng biến trỏ đến địa chỉ bộ nhớ của đối tượng mới ( là [1,2,3])
Và như hình dưới đây cả hai đều cùng trỏ vào một ô nhớ !!

Câu số 3: Liên quan thay đổi chuỗi


Chúng ta sẽ đặt câu hỏi : Tại sao a, b cũng như câu hỏi trên cùng tham chiếu đến một ô nhớ : Tại sao khi b thay đổi mà a lại không thay đổi theo giống như câu hỏi ở trên kia. Điều đó được giải thích qua Mutable vs Immutable Objects trong Python.
String là dạng Immutable , do đó nó không cho phép thay đổi giá trị của bản thân nó. Giá trị tại ô nhớ ban đầu là b :0x7f6d21920fb8 vẫn mãi mãi có giá trị là : ‘jose’.

Sau lệnh b += ‘mourinho’ thì địa chỉ ô nhớ b trỏ đến đã thay đổi : :0x7f6d21920fb8 -> 0x7f6d1f91eb30

Còn về ví dụ List ở trên , nó cho phép chúng ta thay đổi giá trị của bản thân nó ( tại chính ô nhớ đó ) . Vì list là dạng Mutable objects. Xem hình dưới đây :

Rõ ràng tại ô nhớ của b, giá trị đã được thay đổi , còn địa chỉ ô nhớ thì không hề thay đổi nhé .

Câu số 4: Liên quan đến so sánh == và IS


Giải thích : == là toán tử so sánh giá trị của 2 toán hạng, is là toán tử kiểm tra xem cả 2 toán hạng có cùng tham chiếu đến cùng một đối tượng hay không.

Ở đây a, b có giá trị bằng nhau nhưng không tham chiếu đến cùng một đối tượng.

Kết tạm :


Mutable vs Immutable Objects là một phần rất quan trọng đọc ở đây : https://medium.com/@meghamohan/mutable-and-immutable-side-of-python-c2145cf72747

Tài liệu về Python ( chuẩn nhất ) xem ở đây : https://docs.python.org/3/library/copy.html

Trang web để visual code Python : http://www.pythontutor.com/visualize.html#mode=edit

Sâu hơn về chuỗi trong Python : https://medium.com/@daniel.tooke/will-python-intern-my-string-94ea9efc18b2

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo