Con trỏ trong Python với ví dụ là gì?

Mỗi biến có một vị trí bộ nhớ tương ứng và mỗi vị trí bộ nhớ có một địa chỉ tương ứng được xác định cho nó. Con trỏ lưu trữ địa chỉ của các biến khác

Đáng ngạc nhiên là con trỏ không thực sự tồn tại trong Python. Nếu đó là trường hợp, những gì tôi đang viết ở đây?

Mọi thứ đều là đối tượng trong Python. Trong bài viết này, chúng ta sẽ xem xét mô hình đối tượng của Python và xem cách chúng ta có thể giả mạo con trỏ trong Python

Mục lục

Bạn có thể bỏ qua bất kỳ phần cụ thể nào của hướng dẫn con trỏ Python này bằng cách sử dụng mục lục bên dưới

Tại sao con trỏ không tồn tại trong Python?

Không ai biết tại sao con trỏ không tồn tại trong Python

Bạn đã đọc đúng

lý do là không rõ

Ngay cả trong các ngôn ngữ lập trình cơ bản như C và C++, con trỏ được coi là phức tạp

Sự phức tạp này đi ngược lại Zen của Python và đây có thể là lý do tại sao Python không nói về lý do tại sao nó không bao gồm các con trỏ

Nói cách khác, mục tiêu của Python là giữ mọi thứ đơn giản. Con trỏ không được coi là đơn giản

Mặc dù khái niệm về con trỏ là xa lạ với Python, nhưng mục tiêu tương tự có thể được đáp ứng với sự trợ giúp của các đối tượng. Trước khi thảo luận thêm về vấn đề này, trước tiên chúng ta hãy hiểu vai trò của các đối tượng trong Python

Đối tượng là gì?

Mọi thứ đều là đối tượng trong Python

Nếu bạn mới bắt đầu với Python, hãy sử dụng bất kỳ REPL nào và khám phá phương pháp

94169658712768
7 để hiểu điều này

Cụ thể hơn, đoạn mã sau chứng minh rằng các kiểu dữ liệu

94169658712768
8,
94169658712768
9,
x = y
x is y
0 và
x = y
x is y
1 là từng đối tượng trong Python

print[isinstance[int, object]]
print[isinstance[str, object]]
print[isinstance[list, object]]
print[isinstance[bool, object]]

đầu ra

True
True
True
True

Điều này chứng tỏ mọi thứ trong Python đều là đối tượng

Vậy đối tượng là gì?

Một đối tượng Python bao gồm ba phần

  • số tham chiếu
  • Loại
  • Giá trị

Số lượng tham chiếu là số lượng biến tham chiếu đến một vị trí bộ nhớ cụ thể

Loại đề cập đến loại đối tượng. Ví dụ về các loại Python bao gồm

94169658712768
8,
x = y
x is y
3,
x = y
x is y
4 và
x = y
x is y
5

Giá trị là giá trị thực của đối tượng được lưu trữ trong bộ nhớ

Các đối tượng trong Python có hai loại - Bất biến và Có thể thay đổi

Điều quan trọng là phải hiểu sự khác biệt giữa các đối tượng không thay đổi và có thể thay đổi để triển khai hành vi con trỏ trong Python

Trước tiên hãy phân tách các loại dữ liệu trong Python thành các đối tượng không thể thay đổi và có thể thay đổi

ImmutableMutableintlistfloatsetstrdictboolcomplextupleFrozenset

{. blueTable}

Các đối tượng bất biến không thể thay đổi bài tạo. Trong bảng trên, bạn có thể thấy các kiểu dữ liệu thường được sử dụng trong Python đều là các đối tượng bất biến. Hãy xem ví dụ dưới đây

x = 34
y = id[x]
print[y]

Khi bạn chạy tập lệnh này trong môi trường REPL của mình, bạn sẽ nhận được địa chỉ bộ nhớ có giá trị

đầu ra

94562650443584

Bây giờ, hãy thay đổi giá trị của x và xem điều gì sẽ xảy ra. Giá trị của x trong bộ nhớ 94562650443584 là 34 và không thể thay đổi. Nếu chúng ta thay đổi giá trị của x, nó sẽ tạo ra một đối tượng mới

x = 34
y = id[x]
print[y]
x += 1
y= id[x]
print[y]

đầu ra

94169658712736

94169658712768

Sử dụng is[] để xác minh xem hai đối tượng có chia sẻ cùng một địa chỉ bộ nhớ không. Hãy xem một ví dụ

x = y
x is y

Nếu đầu ra là true, nó chỉ ra rằng x và y chia sẻ cùng một địa chỉ bộ nhớ

Các đối tượng có thể thay đổi có thể được chỉnh sửa ngay cả sau khi tạo. Không giống như trong các đối tượng bất biến, không có đối tượng mới nào được tạo khi một đối tượng có thể thay đổi được sửa đổi. Hãy sử dụng đối tượng danh sách là đối tượng có thể thay đổi

numbs = [1, 1, 2, 3, 5]
print["---------Before Modification------------"]
print[id[numbs]]
print[]

## element modification
numbs[0] += 1
print["-----------After Element Modification-------------"]
print[id[numbs]]
print[]

đầu ra

---------Before Modification------------
140469873815424

True
True
True
True
0

Lưu ý rằng địa chỉ của đối tượng vẫn giữ nguyên ngay cả sau khi thực hiện thao tác trên danh sách

Điều này xảy ra vì danh sách là một đối tượng có thể thay đổi. Khái niệm tương tự áp dụng cho các đối tượng có thể thay đổi khác như

x = y
x is y
6 hoặc
x = y
x is y
7 được đề cập trong bảng được trình bày trước đó trong hướng dẫn này

Bây giờ chúng ta đã hiểu sự khác biệt giữa các đối tượng có thể thay đổi và không thể thay đổi, chúng ta hãy xem mô hình đối tượng của Python

Biến trong C so với Biến trong Python

Các biến trong Python rất khác so với các biến trong C hoặc C++

Cụ thể hơn, Python không có biến. Thay vào đó, chúng được gọi bằng tên. Để hiểu các biến trong Python khác với biến trong các ngôn ngữ lập trình cơ bản như C và C++ như thế nào, hãy xem một ví dụ

Đầu tiên, hãy định nghĩa một biến trong C

True
True
True
True
1

Đoạn mã trên thực sự làm gì?

Dòng mã này

  • Cấp phát bộ nhớ cho kiểu dữ liệu đã xác định, trong trường hợp này là
    94169658712768
    8
  • Phân bổ một giá trị
    x = y
    x is y
    9 cho vị trí bộ nhớ, chẳng hạn như
    numbs = [1, 1, 2, 3, 5]
    print["---------Before Modification------------"]
    print[id[numbs]]
    print[]
    
    ## element modification
    numbs[0] += 1
    print["-----------After Element Modification-------------"]
    print[id[numbs]]
    print[]
    0
  • Cho biết biến
    numbs = [1, 1, 2, 3, 5]
    print["---------Before Modification------------"]
    print[id[numbs]]
    print[]
    
    ## element modification
    numbs[0] += 1
    print["-----------After Element Modification-------------"]
    print[id[numbs]]
    print[]
    1 nhận giá trị
    x = y
    x is y
    9

Trong C, nếu bạn muốn thay đổi giá trị của v sau đó, bạn có thể làm điều này

True
True
True
True
2

Bây giờ, giá trị 20 được phân bổ cho vị trí bộ nhớ

numbs = [1, 1, 2, 3, 5]
print["---------Before Modification------------"]
print[id[numbs]]
print[]

## element modification
numbs[0] += 1
print["-----------After Element Modification-------------"]
print[id[numbs]]
print[]
0. Vì biến v là một đối tượng có thể thay đổi nên vị trí của biến không thay đổi mặc dù giá trị của nó thay đổi. Nghĩa là,
numbs = [1, 1, 2, 3, 5]
print["---------Before Modification------------"]
print[id[numbs]]
print[]

## element modification
numbs[0] += 1
print["-----------After Element Modification-------------"]
print[id[numbs]]
print[]
1 được xác định ở đây không chỉ là tên của biến mà còn là vị trí bộ nhớ của nó

Bây giờ, hãy gán giá trị của v cho một biến mới

True
True
True
True
3

Một biến mới mới hiện được tạo với giá trị 20 nhưng biến này sẽ có vị trí bộ nhớ riêng và sẽ không lấy vị trí bộ nhớ của biến có giá trị mà nó đã sao chép

Trong Python, tên hoạt động theo cách tương phản với những gì chúng ta vừa thấy

Hãy viết lại Python tương đương với đoạn mã trên để xem nguyên tắc này hoạt động

True
True
True
True
4

Dòng mã này

  • Tạo một đối tượng Python mới
  • Đặt kiểu dữ liệu cho đối tượng Python là số nguyên
  • Gán giá trị 10 cho PyObject
  • Tạo tên
    numbs = [1, 1, 2, 3, 5]
    print["---------Before Modification------------"]
    print[id[numbs]]
    print[]
    
    ## element modification
    numbs[0] += 1
    print["-----------After Element Modification-------------"]
    print[id[numbs]]
    print[]
    1
  • Điểm
    numbs = [1, 1, 2, 3, 5]
    print["---------Before Modification------------"]
    print[id[numbs]]
    print[]
    
    ## element modification
    numbs[0] += 1
    print["-----------After Element Modification-------------"]
    print[id[numbs]]
    print[]
    1 cho PyObject mới được tạo
  • Tăng số lượt truy cập của đối tượng Python mới được tạo lên 1

Hãy hình dung và làm cho sự hiểu biết của chúng tôi đơn giản

Không giống như trong C, một đối tượng mới được tạo và các đối tượng đó sở hữu vị trí bộ nhớ của biến

Tên được xác định là

numbs = [1, 1, 2, 3, 5]
print["---------Before Modification------------"]
print[id[numbs]]
print[]

## element modification
numbs[0] += 1
print["-----------After Element Modification-------------"]
print[id[numbs]]
print[]
1, hiện sở hữu bất kỳ vị trí bộ nhớ nào

Bây giờ, hãy gán một giá trị khác cho

numbs = [1, 1, 2, 3, 5]
print["---------Before Modification------------"]
print[id[numbs]]
print[]

## element modification
numbs[0] += 1
print["-----------After Element Modification-------------"]
print[id[numbs]]
print[]
1

True
True
True
True
5

Hãy xem những gì xảy ra ở đây

  • Đầu tiên, điều này tạo ra một PyObject mới
  • Đặt kiểu dữ liệu cho PyObject là số nguyên
  • Gán giá trị 20 cho PyObject
  • Điểm v tới PyObject mới được tạo
  • Tăng số lượng truy cập của PyObject mới được tạo lên 1
  • Giảm refcount của PyObject đã tồn tại xuống 1

Tên biến

numbs = [1, 1, 2, 3, 5]
print["---------Before Modification------------"]
print[id[numbs]]
print[]

## element modification
numbs[0] += 1
print["-----------After Element Modification-------------"]
print[id[numbs]]
print[]
1 bây giờ trỏ đến đối tượng mới được tạo. Đối tượng đầu tiên có giá trị
x = y
x is y
9 hiện có số lượng truy cập bằng 0. Điều này sẽ được làm sạch bởi bộ thu gom rác

Bây giờ hãy gán giá trị của

numbs = [1, 1, 2, 3, 5]
print["---------Before Modification------------"]
print[id[numbs]]
print[]

## element modification
numbs[0] += 1
print["-----------After Element Modification-------------"]
print[id[numbs]]
print[]
1 cho một biến mới

True
True
True
True
6

Trong Python, điều này tạo ra một tên mới chứ không phải một đối tượng mới

Bạn có thể xác thực điều này bằng cách sử dụng tập lệnh bên dưới

True
True
True
True
7

Đầu ra sẽ đúng. Lưu ý rằng

---------Before Modification------------
140469873815424
2 vẫn là một đối tượng bất biến. Bạn có thể thực hiện bất kỳ thao tác nào trên
---------Before Modification------------
140469873815424
2 và nó sẽ tạo một đối tượng mới

Hành vi con trỏ trong Python

Bây giờ chúng ta đã hiểu rõ về các đối tượng có thể thay đổi là gì, hãy xem cách chúng ta có thể sử dụng hành vi của đối tượng này để mô phỏng các con trỏ trong Python. Chúng tôi cũng sẽ thảo luận về cách chúng tôi có thể sử dụng các đối tượng Python tùy chỉnh

Sử dụng đối tượng có thể thay đổi

Chúng ta có thể coi các đối tượng có thể thay đổi như con trỏ. Hãy xem cách sao chép mã C bên dưới bằng Python

True
True
True
True
8

Trong đoạn mã trên,

numbs = [1, 1, 2, 3, 5]
print["---------Before Modification------------"]
print[id[numbs]]
print[]

## element modification
numbs[0] += 1
print["-----------After Element Modification-------------"]
print[id[numbs]]
print[]
1 được gán với giá trị
x = y
x is y
9. Giá trị hiện tại được in và sau đó giá trị của
numbs = [1, 1, 2, 3, 5]
print["---------Before Modification------------"]
print[id[numbs]]
print[]

## element modification
numbs[0] += 1
print["-----------After Element Modification-------------"]
print[id[numbs]]
print[]
1 được tăng lên 10 trước khi in giá trị mới. Đầu ra của mã này sẽ là

True
True
True
True
9

Hãy sao chép hành vi này trong Python bằng cách sử dụng một đối tượng có thể thay đổi. Chúng tôi sẽ sử dụng một danh sách và sửa đổi phần tử đầu tiên của danh sách

x = 34
y = id[x]
print[y]
0

đầu ra

x = 34
y = id[x]
print[y]
1

Ở đây,

---------Before Modification------------
140469873815424
7 tăng giá trị phần tử đầu tiên lên một. Vì vậy, điều này có nghĩa là con trỏ có trong Python? . Điều này là có thể bởi vì chúng tôi đã sử dụng một loại có thể thay đổi, danh sách. Hãy thử cùng một mã bằng cách sử dụng tuple. Bạn sẽ nhận được một lỗi

x = 34
y = id[x]
print[y]
2

đầu ra

x = 34
y = id[x]
print[y]
3

Điều này là do tuple là một loại bất biến. Hãy thử sử dụng các đối tượng có thể thay đổi khác để có được đầu ra mong muốn tương tự. Điều quan trọng là phải hiểu rằng chúng ta chỉ giả mạo hành vi của con trỏ bằng cách sử dụng các đối tượng có thể thay đổi

Con trỏ Sử dụng ctypes

Chúng ta có thể tạo các con trỏ thực trong Python bằng cách sử dụng các mô-đun

---------Before Modification------------
140469873815424
8 tích hợp sẵn. Để bắt đầu, hãy lưu trữ các hàm sử dụng con trỏ trong tệp
---------Before Modification------------
140469873815424
9 và biên dịch nó

Viết hàm bên dưới vào tệp

---------Before Modification------------
140469873815424
9 của bạn

x = 34
y = id[x]
print[y]
4

Giả sử tên tệp của chúng tôi là

True
True
True
True
01. Chạy các lệnh dưới đây

x = 34
y = id[x]
print[y]
5

Trong lệnh đầu tiên,

True
True
True
True
01 được biên dịch thành một đối tượng
True
True
True
True
03. Sau đó, tệp đối tượng này được đưa đến sản xuất_______6_______04 để làm việc với
True
True
True
True
05

x = 34
y = id[x]
print[y]
6

đầu ra

x = 34
y = id[x]
print[y]
7

True
True
True
True
06 trả về đối tượng được chia sẻ
True
True
True
True
07. Hãy để chúng tôi định nghĩa hàm
---------Before Modification------------
140469873815424
7 trong đối tượng chia sẻ
True
True
True
True
09. Chúng ta phải sử dụng ctypes để chuyển một con trỏ tới các hàm được xác định trong một đối tượng được chia sẻ

x = 34
y = id[x]
print[y]
8

Chúng ta sẽ gặp lỗi nếu thử gọi hàm này bằng một kiểu khác

x = 34
y = id[x]
print[y]
9

đầu ra

94562650443584
0

Lỗi nói rằng một con trỏ được yêu cầu bởi chức năng. Bạn phải sử dụng biến C trong ctypes để chuyển tham chiếu biến

94562650443584
1

Ở đây

numbs = [1, 1, 2, 3, 5]
print["---------Before Modification------------"]
print[id[numbs]]
print[]

## element modification
numbs[0] += 1
print["-----------After Element Modification-------------"]
print[id[numbs]]
print[]
1 là biến C và
True
True
True
True
11 chuyển tham chiếu biến

đầu ra

94562650443584
2

Suy nghĩ cuối cùng

Như chúng ta đã thấy trong hướng dẫn này, hành vi của con trỏ có thể được triển khai trong Python mặc dù về mặt kỹ thuật chúng không có sẵn trong ngôn ngữ Python

Mặc dù chúng tôi đã sử dụng các đối tượng có thể thay đổi để mô phỏng hành vi của con trỏ, nhưng con trỏ ctype là con trỏ thực

Nếu bạn thích bài viết này, hãy nhớ tham gia bản tin Nhà phát triển hàng tháng của tôi, nơi tôi gửi những tin tức mới nhất từ ​​thế giới Python và JavaScript

Con trỏ trong Python là gì?

Con trỏ về cơ bản là biến chứa địa chỉ bộ nhớ của biến khác . Chúng cho phép bạn tạo hiệu quả cao trong các phần mã của mình nhưng có thể dẫn đến nhiều lỗi quản lý bộ nhớ khác nhau. Bạn sẽ tìm hiểu về mô hình đối tượng của Python và xem tại sao con trỏ trong Python không thực sự tồn tại.

con trỏ với ví dụ là gì?

Con trỏ là biến lưu địa chỉ của biến khác . Không giống như các biến khác giữ giá trị của một loại nhất định, con trỏ giữ địa chỉ của một biến. Ví dụ: một biến số nguyên chứa [hoặc bạn có thể nói là lưu trữ] một giá trị số nguyên, tuy nhiên, một con trỏ số nguyên giữ địa chỉ của một biến số nguyên.

Con trỏ là gì và tại sao nó được sử dụng?

Con trỏ là biến lưu địa chỉ bộ nhớ . Con trỏ được sử dụng để lưu trữ địa chỉ của các biến hoặc mục bộ nhớ khác. Con trỏ rất hữu ích cho một kiểu truyền tham số khác, thường được gọi là Truyền theo địa chỉ. Con trỏ rất cần thiết để cấp phát bộ nhớ động.

Ví dụ về biến con trỏ là gì?

Khi nó được sử dụng trong một khai báo [e. g. , int * pNumber], nó biểu thị rằng tên theo sau là một biến con trỏ . Trong khi đó khi nó được sử dụng trong một biểu thức [e. g. , *pNumber = 99; .

Chủ Đề