Hướng dẫn can we use pointer in python? - chúng ta có thể sử dụng con trỏ trong python không?
Xem bây giờ hướng dẫn này có một khóa học video liên quan được tạo bởi nhóm Python thực sự. Xem nó cùng với hướng dẫn bằng văn bản để hiểu sâu hơn về sự hiểu biết của bạn: Con trỏ và đồ vật trong Python This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Pointers and Objects in Python Show
Nếu bạn đã từng làm việc với các ngôn ngữ cấp thấp hơn như C hoặc C ++, thì bạn có thể nghe nói về con trỏ. Con trỏ cho phép bạn tạo ra hiệu quả tuyệt vời trong các phần của mã của bạn. Chúng cũng gây ra sự nhầm lẫn cho người mới bắt đầu và có thể dẫn đến các lỗi quản lý bộ nhớ khác nhau, ngay cả đối với các chuyên gia. Vậy họ đang ở đâu trong Python, và làm thế nào bạn có thể mô phỏng con trỏ trong Python? Con trỏ được sử dụng rộng rãi trong C và C ++. Về cơ bản, chúng là các biến giữ địa chỉ bộ nhớ của một biến khác. Đối với việc bồi dưỡng trên các con trỏ, bạn có thể xem xét kiểm tra tổng quan này trên các con trỏ C. Trong bài viết này, bạn sẽ hiểu rõ hơn về mô hình đối tượng Python và tìm hiểu lý do tại sao con trỏ trong Python don lồng thực sự tồn tại. Đối với các trường hợp bạn cần bắt chước hành vi con trỏ, bạn sẽ học cách mô phỏng con trỏ trong Python mà không cần cơn ác mộng quản lý bộ nhớ. Trong bài viết này, bạn sẽ:
Tại sao không có Python có con trỏ?Sự thật là tôi không biết. Con trỏ trong Python có thể tồn tại tự nhiên? Có lẽ, nhưng con trỏ dường như đi ngược lại Zen of Python. Con trỏ khuyến khích những thay đổi ngầm hơn là rõ ràng. Thông thường, chúng phức tạp thay vì đơn giản, đặc biệt là cho người mới bắt đầu. Thậm chí tệ hơn, họ cầu xin những cách để tự bắn vào chân mình, hoặc làm điều gì đó thực sự nguy hiểm như đọc từ một phần của bộ nhớ mà bạn không nên làm. Python có xu hướng cố gắng trừu tượng hóa các chi tiết triển khai như địa chỉ bộ nhớ từ người dùng. Python thường tập trung vào khả năng sử dụng thay vì tốc độ. Kết quả là, con trỏ trong Python don lồng thực sự có ý nghĩa. Mặc dù không sợ hãi, Python, theo mặc định, cung cấp cho bạn một số lợi ích của việc sử dụng con trỏ. Hiểu gợi ý trong Python đòi hỏi một đường vòng ngắn vào các chi tiết triển khai của Python. Cụ thể, bạn sẽ cần phải hiểu:
Giữ địa chỉ bộ nhớ của bạn và để bắt đầu. Đối tượng trong PythonTrong Python, mọi thứ đều là một đối tượng. Để chứng minh, bạn có thể mở ra một bản phát hành và khám phá bằng 2:>>>
Mã này cho bạn thấy rằng mọi thứ trong Python thực sự là một đối tượng. Mỗi đối tượng chứa ít nhất ba phần dữ liệu:
Số lượng tham chiếu là để quản lý bộ nhớ. Để có cái nhìn sâu sắc về nội bộ của quản lý bộ nhớ trong Python, bạn có thể đọc quản lý bộ nhớ bằng Python. Loại được sử dụng ở lớp Cpython để đảm bảo loại an toàn trong thời gian chạy. Cuối cùng, có giá trị, là giá trị thực tế được liên kết với đối tượng. Không phải tất cả các đối tượng đều giống nhau mặc dù. Có một sự khác biệt quan trọng khác mà bạn sẽ cần phải hiểu: các đối tượng bất biến và có thể thay đổi. Hiểu được sự khác biệt giữa các loại đối tượng thực sự giúp làm rõ lớp đầu tiên của hành tây là con trỏ trong Python. Các đối tượng bất biến và có thể thay đổiTrong Python, có hai loại đối tượng:
Hiểu được sự khác biệt này là chìa khóa đầu tiên để điều hướng cảnh quan của con trỏ trong Python. Ở đây, một sự cố của các loại phổ biến và liệu chúng có thể thay đổi hay không thay đổi:
Các đối tượng bất biến và có thể thay đổi
Các đối tượng có thể thay đổi có thể được thay đổi. >>>
Mã này cho bạn thấy rằng mọi thứ trong Python thực sự là một đối tượng. Mỗi đối tượng chứa ít nhất ba phần dữ liệu: >>>
Mã này cho bạn thấy rằng mọi thứ trong Python thực sự là một đối tượng. Mỗi đối tượng chứa ít nhất ba phần dữ liệu: Số lượng tham chiếu >>>
Mã này cho bạn thấy rằng mọi thứ trong Python thực sự là một đối tượng. Mỗi đối tượng chứa ít nhất ba phần dữ liệu: Số lượng tham chiếu >>>
Mã này cho bạn thấy rằng mọi thứ trong Python thực sự là một đối tượng. Mỗi đối tượng chứa ít nhất ba phần dữ liệu: Đối chiếu rằng với một đối tượng có thể thay đổi, như 0:>>>
Mã này cho thấy một sự khác biệt lớn trong hai loại đối tượng. 6 có ID ban đầu. Ngay cả sau khi 7 được thêm vào danh sách, 6 cũng có cùng ID. Điều này là do loại 0 là có thể thay đổi.Một cách khác để chứng minh rằng danh sách là có thể thay đổi là với nhiệm vụ: >>>
Mã này cho thấy một sự khác biệt lớn trong hai loại đối tượng. 6 có ID ban đầu. Ngay cả sau khi 7 được thêm vào danh sách, 6 cũng có cùng ID. Điều này là do loại 0 là có thể thay đổi.Một cách khác để chứng minh rằng danh sách là có thể thay đổi là với nhiệm vụ:Trong mã này, bạn đột biến 6 và đặt phần tử đầu tiên của nó thành 1. Tuy nhiên, nó duy trì cùng một ID ngay cả sau nhiệm vụ này. Với các đối tượng có thể thay đổi và bất biến ngoài đường, bước tiếp theo trên hành trình của bạn đến Python Khai sáng là hiểu về hệ sinh thái biến Python.Hiểu các biến Các biến Python về cơ bản khác với các biến trong C hoặc C ++. Trên thực tế, Python không có biến số này. Python có tên, không phải biến. Điều này có vẻ như phạm vi, và phần lớn, nó là. Hầu hết thời gian, nó hoàn toàn chấp nhận được khi nghĩ về các tên Python là biến, nhưng hiểu được sự khác biệt là rất quan trọng. Điều này đặc biệt đúng khi bạn điều hướng chủ đề khó khăn của con trỏ trong Python.Để giúp lái xe về nhà sự khác biệt, bạn có thể xem cách các biến hoạt động trong C, những gì chúng đại diện, và sau đó tương phản với cách tên hoạt động trong Python. Các biến trong c
Gán giá trị 3 cho vị trí bộ nhớ đóChỉ ra rằng 7 chỉ vào giá trị đóThể hiện trong một chế độ xem đơn giản của bộ nhớ, nó có thể trông như thế này:mutable. The updated memory layout shows the new value: Ở đây, bạn có thể thấy rằng biến 7 có vị trí bộ nhớ giả là 6 và giá trị 3. Nếu sau này trong chương trình, bạn muốn thay đổi giá trị của 7, bạn có thể thực hiện như sau:Mã trên gán một giá trị mới ( 9) cho biến 7, do đó ghi đè lên giá trị trước đó. Điều này có nghĩa là biến 7 có thể thay đổi. Bố cục bộ nhớ được cập nhật hiển thị giá trị mới:Lưu ý rằng vị trí của 7 didn thay đổi, chỉ là giá trị. Đây là một điểm quan trọng. Nó có nghĩa là 7 là vị trí bộ nhớ, không chỉ là tên cho nó.Một cách khác để nghĩ về khái niệm này là về quyền sở hữu. Theo một nghĩa nào đó, 7 sở hữu vị trí bộ nhớ. 7, lúc đầu, là một hộp trống có thể phù hợp với chính xác một số nguyên trong đó các giá trị số nguyên có thể được lưu trữ.Khi bạn gán một giá trị cho 7, bạn sẽ đặt một giá trị trong hộp mà 7 sở hữu. Nếu bạn muốn giới thiệu một biến mới ( 8), bạn có thể thêm dòng mã này:Mã này tạo ra một hộp mới có tên 8 và sao chép giá trị từ 7 vào hộp. Bây giờ bố cục bộ nhớ sẽ trông như thế này:Lưu ý vị trí mới 1 của 8. Mặc dù giá trị của 7 đã được sao chép lên 8, biến 8 sở hữu một số địa chỉ mới trong bộ nhớ. Do đó, bạn có thể ghi đè giá trị của 8 mà không ảnh hưởng đến 7:Bây giờ bố cục bộ nhớ sẽ trông như thế này:Một lần nữa, bạn đã sửa đổi giá trị tại 8, nhưng không phải là vị trí của nó. Ngoài ra, bạn hoàn toàn không ảnh hưởng đến biến 7 ban đầu. Điều này trái ngược hoàn toàn với cách các tên Python hoạt động.Tên trong Python Python không có biến. Nó có tên. Vâng, đây là một điểm phạm vi, và bạn chắc chắn có thể sử dụng thuật ngữ biến nhiều như bạn muốn. Điều quan trọng là phải biết rằng có một sự khác biệt giữa các biến và tên.
Điểm 7 đến 0 mớiTăng số tiền của 0 lên 1Trong bộ nhớ, nó có thể trông giống như thế này: Bạn có thể thấy rằng bố cục bộ nhớ khác rất nhiều so với bố cục C từ trước. Thay vì 7 sở hữu khối bộ nhớ trong đó giá trị 3 cư trú, đối tượng Python mới được tạo sở hữu bộ nhớ nơi 3 sống. Tên Python 7 không trực tiếp sở hữu bất kỳ địa chỉ bộ nhớ nào theo cách biến C 7 sở hữu một khe tĩnh trong bộ nhớ.Mã này:
Bây giờ trong bộ nhớ, nó sẽ trông giống như thế này: Sơ đồ này giúp minh họa rằng 7 trỏ đến một tham chiếu đến một đối tượng và không sở hữu không gian bộ nhớ như trước đây. Nó cũng cho thấy lệnh 13 không phải là một nhiệm vụ, mà là ràng buộc tên 7 với một tham chiếu.Ngoài ra, đối tượng trước đó (giữ giá trị 3) hiện đang ngồi trong bộ nhớ với số lượng tham chiếu là 0 và sẽ được dọn dẹp bởi người thu gom rác.Bạn có thể giới thiệu một tên mới, 8, vào hỗn hợp như trong ví dụ C:Trong bộ nhớ, bạn sẽ có một tên mới, nhưng không nhất thiết là một đối tượng mới: Bây giờ bạn có thể thấy rằng một đối tượng Python mới chưa được tạo, chỉ là một tên mới chỉ vào cùng một đối tượng. Ngoài ra, đối tượng REFCOUNT đã tăng thêm một. Bạn có thể kiểm tra công bằng nhận dạng đối tượng để xác nhận rằng chúng giống nhau: Mã trên chỉ ra rằng 7 và 8 là cùng một đối tượng. Đừng nhầm lẫn mặc dù: 8 vẫn còn bất biến.Ví dụ: bạn có thể thực hiện bổ sung trên 8:>>>
Sau cuộc gọi bổ sung, bạn được trả lại với một đối tượng Python mới. Bây giờ, bộ nhớ trông như thế này: Một đối tượng mới đã được tạo và 8 hiện chỉ vào đối tượng mới. Thật thú vị, đây là cùng một trạng thái kết thúc nếu bạn đã ràng buộc 8 với 23 trực tiếp:Tuyên bố trên dẫn đến cùng trạng thái bộ nhớ cuối như bổ sung. Để tóm tắt lại, trong Python, bạn không chỉ định các biến. Thay vào đó, bạn liên kết tên với các tài liệu tham khảo. Một lưu ý về các đối tượng thực tập trong PythonBây giờ bạn đã hiểu làm thế nào các đối tượng Python được tạo ra và tên bị ràng buộc với các đối tượng đó, đã đến lúc ném một cái cờ lê vào máy móc. Cờ lê đó đi theo tên của các đối tượng thực tập. Giả sử bạn có mã Python sau: >>>
Sau cuộc gọi bổ sung, bạn được trả lại với một đối tượng Python mới. Bây giờ, bộ nhớ trông như thế này: >>>
Sau cuộc gọi bổ sung, bạn được trả lại với một đối tượng Python mới. Bây giờ, bộ nhớ trông như thế này:
Tạo đối tượng Python (________ 126) Gán tên 7 cho đối tượng đó>>> 0Sau cuộc gọi bổ sung, bạn được trả lại với một đối tượng Python mới. Bây giờ, bộ nhớ trông như thế này: Một đối tượng mới đã được tạo và 8 hiện chỉ vào đối tượng mới. Thật thú vị, đây là cùng một trạng thái kết thúc nếu bạn đã ràng buộc 8 với 23 trực tiếp:
Bây giờ bạn đã hiểu làm thế nào các đối tượng Python được tạo ra và tên bị ràng buộc với các đối tượng đó, đã đến lúc ném một cái cờ lê vào máy móc. Cờ lê đó đi theo tên của các đối tượng thực tập. Giả sử bạn có mã Python sau: >>> 1Sau cuộc gọi bổ sung, bạn được trả lại với một đối tượng Python mới. Bây giờ, bộ nhớ trông như thế này: >>> 2Sau cuộc gọi bổ sung, bạn được trả lại với một đối tượng Python mới. Bây giờ, bộ nhớ trông như thế này: Một đối tượng mới đã được tạo và 8 hiện chỉ vào đối tượng mới. Thật thú vị, đây là cùng một trạng thái kết thúc nếu bạn đã ràng buộc 8 với 23 trực tiếp:Mô phỏng con trỏ trong PythonChỉ vì các con trỏ trong Python don lồng tồn tại tự nhiên không có nghĩa là bạn có thể nhận được những lợi ích của việc sử dụng con trỏ. Trong thực tế, có nhiều cách để mô phỏng con trỏ trong Python. Bạn sẽ học hai trong phần này:
Được rồi, hãy để Lừa đi đến điểm. Sử dụng các loại có thể thay đổi làm con trỏBạn đã học về các loại có thể thay đổi. Bởi vì những đối tượng này có thể thay đổi, bạn có thể đối xử với chúng như thể chúng là con trỏ để mô phỏng hành vi con trỏ. Giả sử bạn muốn sao chép mã C sau: 3Mã này đưa một con trỏ tới một số nguyên ( 44) và sau đó tăng giá trị lên một. Đây là một chức năng chính để thực hiện mã: 4Trong mã trên, bạn gán 3 cho 8, in ra giá trị hiện tại, tăng giá trị lên một và sau đó in ra giá trị sửa đổi. Đầu ra của việc thực thi mã này sẽ như sau:Một cách để tái tạo loại hành vi này trong Python là bằng cách sử dụng một loại có thể thay đổi. Cân nhắc sử dụng danh sách và sửa đổi phần tử đầu tiên: >>> 5Ở đây, 47 truy cập phần tử đầu tiên và tăng giá trị của nó. Sử dụng 0 có nghĩa là kết quả cuối cùng dường như đã sửa đổi giá trị. Vì vậy, gợi ý trong Python có tồn tại? Ồ không. Điều này chỉ có thể vì 0 là một loại có thể thay đổi. Nếu bạn đã cố gắng sử dụng 7, bạn sẽ gặp lỗi:>>> 6Ở đây, 47 truy cập phần tử đầu tiên và tăng giá trị của nó. Sử dụng 0 có nghĩa là kết quả cuối cùng dường như đã sửa đổi giá trị. Vì vậy, gợi ý trong Python có tồn tại? Ồ không. Điều này chỉ có thể vì 0 là một loại có thể thay đổi. Nếu bạn đã cố gắng sử dụng 7, bạn sẽ gặp lỗi:Mã trên chứng minh rằng 7 là bất biến. Do đó, nó không hỗ trợ gán mục. 0 không phải là loại có thể thay đổi duy nhất. Một cách tiếp cận phổ biến khác để bắt chước các con trỏ trong Python là sử dụng 2.>>> 7Ở đây, 47 truy cập phần tử đầu tiên và tăng giá trị của nó. Sử dụng 0 có nghĩa là kết quả cuối cùng dường như đã sửa đổi giá trị. Vì vậy, gợi ý trong Python có tồn tại? Ồ không. Điều này chỉ có thể vì 0 là một loại có thể thay đổi. Nếu bạn đã cố gắng sử dụng 7, bạn sẽ gặp lỗi:Mã trên chứng minh rằng 7 là bất biến. Do đó, nó không hỗ trợ gán mục. 0 không phải là loại có thể thay đổi duy nhất. Một cách tiếp cận phổ biến khác để bắt chước các con trỏ trong Python là sử dụng 2.Hãy nói rằng bạn đã có một ứng dụng mà bạn muốn theo dõi mỗi khi một sự kiện thú vị xảy ra. Một cách để đạt được điều này là tạo ra >>> s[0] = "R"
Traceback (most recent call last):
File " |