Một điều tôi thấy thực sự hữu ích khi tôi hiểu rõ hơn về Python là hiểu cách nó gán các đối tượng cho các địa chỉ bộ nhớ. Điều này cuối cùng cũng khá đơn giản, nhưng theo tôi đó là cách tốt nhất để hiểu phép gán biến và các toán tử đẳng thức
Một trong những điều đầu tiên bạn thường nói về Python là mọi thứ đều là đối tượng. Mọi điều. Mỗi và mọi chuỗi, số, danh sách, từ điển, lớp, hàm, các đối tượng boolean >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]7 và >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]8, và đối tượng >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]9. Python sẽ lưu trữ chúng tại một địa chỉ bộ nhớ cụ thể và bạn có thể tìm ra vị trí chúng được lưu trữ trong bộ nhớ bằng cách sử dụng hàm >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]0
4304841504>>> id(str)
4304548256>>> id(True)
4304449920
- Ghi chú. Điều này giả định rằng bạn đang sử dụng phiên bản 3 trở lên của CPython tiêu chuẩn
Khi gán một biến, bạn có thể nghĩ rằng mỗi biến là một đối tượng mới, nhưng điều đó không hẳn đúng
>>> a = [1, 2, 3]>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]
Khi tôi mới bắt đầu học Python, tôi đã từng nghĩ rằng bây giờ tôi có hai danh sách riêng biệt, >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]1 và >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]0, và có thể thực hiện bất kỳ thay đổi nào đối với chúng mà tôi muốn độc lập với danh sách kia. Nhưng không, như đã thấy ở đây, bất kỳ thay đổi nào được thực hiện đối với >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]0 trong ví dụ trên cũng ảnh hưởng đến >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]1 và ngược lại
Tôi thấy cách dễ nhất để giải thích điều này là hãy nhớ rằng khi bạn gán một biến, bạn thực sự đang trỏ biến đó tới một địa chỉ bộ nhớ. Vì vậy, khi tôi thực hiện >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]3, tôi đã tạo một đối tượng danh sách mới trong bộ nhớ, sau đó lưu >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]1 dưới dạng một biến trỏ đến địa chỉ bộ nhớ của đối tượng đó. Và những gì tôi đã làm trong ví dụ trên là trỏ hai biến, >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]1 và >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]0, đến cùng một địa chỉ bộ nhớ
4522039944>>> id(b)
4522039944
Khi bạn sử dụng >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]1 hoặc >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]0 trong mã Python tiếp theo của mình, chương trình thực sự đang làm gì và truy xuất đối tượng mà nó trỏ tới tại địa chỉ bộ nhớ >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]9. Nếu sau đó bạn gán lại >>> a = [1, 2, 3]
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]0 cho một số đối tượng khác, e. g. >>> id(a)
4522039944>>> id(b)
45220399441, thay vào đó, nó trỏ đến một địa chỉ bộ nhớ khác, nơi có một đối tượng khác được lưu trữ
Ngẫu nhiên, nếu tôi thực sự muốn tạo hai đối tượng danh sách khác nhau như trong ví dụ của tôi ở trên, thì cách để thực hiện việc này là sử dụng hàm >>> id(a)
4522039944>>> id(b)
45220399442 của Python
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]2
Bây giờ chúng ta có hai đối tượng danh sách riêng biệt, tại hai địa chỉ bộ nhớ riêng biệt và có thể thêm/xóa các mục vào chúng một cách độc lập
Cuối cùng, một lý do khác khiến tôi cảm thấy việc hiểu các địa chỉ bộ nhớ là hữu ích vì đó là cách rõ ràng nhất để hiểu các toán tử đẳng thức, đặc biệt là >>> id(a)
4522039944>>> id(b)
45220399443
Nói tóm lại, double equals >>> id(a)
4522039944>>> id(b)
45220399444 có thể được sử dụng để so sánh hai đối tượng và xem liệu chúng có bằng nhau không (với hai danh sách, điều đó đòi hỏi chúng phải có cùng nội dung). Ngược lại, toán tử >>> id(a)
4522039944>>> id(b)
45220399443 sẽ kiểm tra xem chúng có phải là cùng một đối tượng hay không, điều này có nghĩa là chúng có cùng địa chỉ bộ nhớ
>>> b = a
>>> b.append(4)
>>> print(a)
[1, 2, 3, 4]6
Như tôi đã nói- điều này thật đơn giản khi bạn hiểu nó, nhưng tôi thấy nó hữu ích như một nguyên tắc cơ bản, không chỉ coi các đối tượng là 'thứ' ẩn dụ tồn tại trong vũ trụ Python, mà còn được đặt ở một vị trí cụ thể trong ký ức, . Có một vài mẩu tin thú vị khác xuất phát từ sự hiểu biết này, chẳng hạn như thực tập và thu gom rác, và tôi sẽ đề cập đến những điều đó trong một số bài viết tiếp theo của mình