logo

Pointer în Python | De ce Python nu acceptă pointer

În acest tutorial, vom afla despre pointer în Python și vom vedea de ce Python nu acceptă concepte de pointer.

Vom înțelege, de asemenea, cum putem simula pointerul în Python. Mai jos este introducerea indicatorului pentru cei care nu au nimic despre el.

Vom înțelege, de asemenea, cum putem simula pointerul în Python. Mai jos este introducerea indicatorului pentru cei care nu au nimic despre el.

Ce este Pointer?

Pointer este un instrument foarte popular și util pentru a stoca adresa variabilei. Dacă cineva a lucrat vreodată cu un limbaj de nivel scăzut, cum ar fi C . C++ , probabil că el/ea ar fi familiarizat cu indicatorii. Gestionează codul foarte eficient. Poate fi ușor dificil pentru începători, dar este unul dintre conceptele importante ale programului. Cu toate acestea, poate duce la diverse erori de gestionare a memoriei. Astfel, definiția indicatorilor -

„Pointerele sunt variabilele care dețin adresa de memorie a altei variabile. Variabilele pointer sunt reprezentate prin asterisc (*).'

Să vedem următorul exemplu de pointer în limbajul de programare C.

Exemplu - Cum se utilizează indicatorul în C

 #include int main() { int* po, o; 0 = 10; printf('Address of c: %p
', &c); printf('Value of c: %d

', c); o = &0; printf('Address of pointer pc: %p
', o); printf('Content of pointer pc: %d

', *o); 0 = 11; printf('Address of pointer pc: %p
', p0); printf('Content of pointer pc: %d

', *p0); *po = 2; printf('Address of c: %p
', &o); printf('Value of c: %d

', o); return 0; } 

Ieșire:

Address of o: 2686784 Value of o: 22 Address of pointer po: 2686784 Content of pointer po: 22 Address of pointer po: 2686784 Content of pointer po: 11 Address of o: 2686784 Value of o: 2 

Pe lângă faptul că sunt utile, indicatorii nu sunt utilizați în Piton . În acest subiect, vom discuta despre modelul obiect al lui Python și vom afla de ce pointerii în Python nu există. De asemenea, vom învăța diferite moduri de a simula pointerii în Python. Mai întâi, să discutăm de ce Python nu acceptă Pointers.

De ce Python nu acceptă pointerii

Motivul exact pentru care nu este susținut indicatorul nu este clar. Ar putea pointerul în Python să existe nativ? Conceptul principal al Python este simplitatea sa, dar pointerul a încălcat Zen din Python. Indicatorii sunt încurajați în principal modificări implicite, mai degrabă decât cele explicite. Sunt și complexe, mai ales pentru începători.

Pointerii tind să creeze complexitate în cod, unde Python se concentrează mai degrabă pe uzabilitate decât pe viteză. Ca rezultat, Python nu acceptă pointer. Cu toate acestea, Python oferă câteva beneficii ale utilizării indicatorului.

Înainte de a înțelege pointerul în Python, trebuie să avem ideea de bază a următoarelor puncte.

  • Obiecte imuabile vs. mutabile
  • Variabile/nume Python

Obiecte în Python

În Python, totul este un obiect, chiar și o clasă, funcții, variabile etc. Fiecare obiect conține cel puțin trei date.

pereche c++
  • Număr de referințe
  • Tip
  • Valoare

Să discutăm unul câte unul.

Număr de referințe - Este folosit pentru gestionarea memoriei. Pentru a obține mai multe informații despre gestionarea memoriei Python, citiți Gestionarea memoriei în Python.

Tip - The CPython stratul este utilizat ca tip pentru a asigura siguranța tipului în timpul rulării. În cele din urmă, există o valoare, care este valoarea reală asociată cu obiectul.

Dacă mergem în profunzime în acest obiect, vom descoperi că nu toate obiectele sunt totuși la fel. Distincția importantă dintre tipurile de obiect este imuabilă și mutabilă. În primul rând, trebuie să înțelegem diferența dintre tipurile de obiect, deoarece explorează pointerul în Python.

Obiecte imuabile vs

Obiectele imuabile nu pot fi modificate, unde obiectele mutabile pot fi modificate. Să vedem următorul tabel cu tipuri comune și dacă sunt sau nu modificabile.

liste de latex
Obiecte Tip
Int Imuabil
Pluti Imuabil
Bool Imuabil
Listă Mutabil
A stabilit Mutabil
Complex Mutabil
Tuplu Imuabil
Frozenset Imuabil
Dict Mutabil

Putem verifica tipul obiectelor de mai sus folosind id() metodă. Această metodă returnează adresa de memorie a obiectului.

Introducem rândurile de mai jos într-un mediu REPL.

 x = 5 id(x) 

Ieșire:

140720979625920 

În codul de mai sus, i-am atribuit valoarea 10 lui x. dacă am modifica această valoare cu substituție, am obține noile obiecte.

 x-=1 id(x) 

Ieșire:

140720979625888 

După cum putem vedea, modificăm codul de mai sus și obținem obiecte noi ca răspuns. Să luăm un alt exemplu de str .

 s = 'java' print(id(s)) s += 'Tpoint' print(s) id(s) 

Ieșire:

2315970974512 JavaTpoint 1977728175088 

Din nou, modificăm valoarea lui x adăugând un șir nou și obținem noua adresă de memorie. Să încercăm să adăugăm șir direct în s.

 s = 'java' s[0] = T print(id(s)) 

Ieșire:

Traceback (most recent call last): File 'C:/Users/DEVANSH SHARMA/PycharmProjects/MyPythonProject/python1.py', line 34, in s[0] = T NameError: name 'T' is not defined 

Codul de mai sus returnează eroare, înseamnă că șirul nu acceptă mutația. Asa de str sunt obiectele imuabile.

Acum, vom vedea obiectul mutabil, cum ar fi lista.

 my_list = [3, 4, 8] print(id(my_list)) my_list.append(4) print(my_list) print(id(my_list)) 

Ieșire:

2571132658944 [3, 4, 8, 4] 2571132658944 

După cum putem vedea în codul de mai sus, lista mea are id-ul inițial și am adăugat cu 5 la listă; lista mea are același id, deoarece lista acceptă mutabilitate.

Înțelegerea variabilelor Python

Modul de definire a variabilelor în Python este mult diferit de C sau C++. Variabila Python nu definește tipul de date. De fapt, Python are nume, nu variabile.

Așa că trebuie să înțelegem diferența dintre variabile și nume și mai ales adevărată atunci când navigăm în subiectul dificil al pointerilor în Python.

Să înțelegem cum funcționează variabila în C și cum funcționează numele în Python.

Variabile în C

În limbajul C, o variabilă este aceea că deține valoare sau valoare de stocare. Este definit cu tipul de date. Să vedem următorul cod care definește variabila.

 int x = 286; 
  • Alocați suficientă memorie pentru un număr întreg.
  • Atribuim valoarea 286 acelei locații de memorie.
  • x reprezintă acea valoare.

Dacă reprezentăm viziunea memoriei -

Pointer în Python

După cum putem vedea, x are o locație de memorie pentru valoarea 286. Acum, vom atribui noua valoare lui x.

linux cum se redenumește un director

x = 250

Această nouă valoare suprascrie valoarea anterioară. Înseamnă că variabila x este mutabilă.

Locația valorii lui x este aceeași, dar valoarea sa schimbat. Este un punct semnificativ care indică faptul că x este locația de memorie, nu doar numele acesteia.

Acum, introducem noua variabilă care ia x, apoi y creează noua casetă de memorie.

 int y = x; 

Variabila y creează o nouă casetă numită y copiază valoarea de la x în casetă.

Pointer în Python

Nume în Python

După cum am discutat mai devreme, Python nu are variabile. Are nume și folosim acest termen ca variabile. Dar există o diferență între variabile și nume. Să vedem următorul exemplu.

 x = 289 

Codul de mai sus este defalcat în timpul execuției.

  1. Creați un PyObject
  2. Setați codul de tip la un număr întreg pentru PyObject
  3. Setați valoarea la 289 pentru PyObject
  4. Creați un nume numit x
  5. Indicați x către noul PyObject
  6. Creșteți refcount-ul PyObject cu 1

Va arăta ca mai jos.

Pointer în Python

Putem înțelege funcționarea internă a unei variabile în Python. Variabila x indică referința obiectului și nu are spațiul de memorie ca înainte. De asemenea, arată că x = 289 leagă numele x la o referință.

Acum, introducem o nouă variabilă și îi atribuim x.

 y = x 

În Python, variabila y nu va crea noul obiect; este doar un nume nou care indică același obiect. Obiectul refcount a crescut de asemenea cu unu. O putem confirma după cum urmează.

 y is x 

Ieșire:

True 

Dacă mărim valoarea lui y cu unu, nu se va mai referi la același obiect.

 y + =1 y is x 

Asta înseamnă că, în Python, nu atribuim variabile. În schimb, legăm numele de referințe.

Simularea pointerilor în Python

După cum am discutat, Python nu acceptă pointer, dar putem obține beneficiile utilizării unui pointer. Python oferă modalități alternative de utilizare a indicatorului în Python. Aceste două moduri sunt prezentate mai jos.

  • Folosind tipuri mutabile ca indicatori
  • Folosind obiecte Python personalizate

Să înțelegem punctele date.

Utilizarea tipurilor modificabile ca indicator

În secțiunea anterioară, am definit obiectele de tip mutabil; le putem trata ca și cum ar fi pointeri pentru a simula comportamentul pointerului. Să înțelegem următorul exemplu.

C

 void add_one(int *a) { *a += 1; } 

În codul de mai sus, am definit pointerul *a, apoi creștem valoarea cu unu. Acum, îl vom implementa cu funcția main().

ce este maven
 #include int main(void) { int y = 233; printf('y = %d
', y); add_one(&y); printf('y = %d
', y); return 0; } 

Ieșire:

y = 233 y = 234 

Putem simula acest tip de comportament folosind tipul mutabil Python. Înțelegeți următorul exemplu.

 def add_one(x): x[0] += 1 y = [2337] add_one(y) y[0] 

Funcția de mai sus accesează primul element al listei și crește valoarea acestuia cu unu. Când executăm programul de mai sus, acesta afișează valoarea modificată a lui y. Înseamnă că putem replica indicatorul folosind obiectul mutabil. Dar dacă încercăm să simulăm pointerul folosind obiect imuabil.

 z = (2337,) add_one(z) 

Ieșire:

Traceback (most recent call last): File '', line 1, in File '', line 2, in add_one TypeError: 'tuple' object does not support item assignment 

Am folosit tuplu din codul de mai sus, un obiect imuabil, așa că a returnat eroarea. De asemenea, putem folosi dicționarul pentru a simula pointerul în Python.

Să înțelegem următorul exemplu în care vom număra fiecare operație care are loc în program. Putem folosi dict pentru a realiza acest lucru.

Exemplu -

 count = {'funcCalls': 0} def car(): count['funcCalls'] += 1 def foo(): count['funCcalls'] += 1 car() foo() count['funcCalls'] 

Ieșire:

2 

Explicație -

În exemplul de mai sus, am folosit numara dicționar, care ținea evidența numărului de apeluri de funcții. Cand foo() funcția este numită, contorul crește cu 2 deoarece dict este mutabil.

Utilizarea obiectelor Python

În exemplul anterior, am folosit dict pentru a emula indicatorul în Python, dar uneori devine dificil să ne amintim toate numele cheilor folosite. Putem folosi clasa personalizată Python în locul dicționarului. Să înțelegem următorul exemplu.

Exemplu -

 class Pointer(object): def __init__(self): self._metrics = { 'funCalls': 0, 'catPictures': 0, } 

În codul de mai sus, am definit clasa Pointer. Această clasă a folosit dict pentru păstrarea datelor reale în variabila membru _metrics. Va oferi mutabilitate programului nostru. Putem face acest lucru după cum urmează.

 class Pointer(object): # ... @property def funCalls(self): return self._metrics['func_calls'] @property def catPictures_served(self): return self._metrics['cat_pictures_served'] 

Noi am folosit @proprietate decorator. Dacă nu sunteți familiarizat cu decoratorii, vizitați tutorialul nostru pentru decoratori Python. Decoratorul @property va accesa funCalls și catPicture_served. Acum, vom crea un obiect din clasa Pointer.

 pt = Pointer() pt.funCalls() pt.catPicture_served 

Aici trebuie să creștem aceste valori.

 class Pointer(object): # ... def increament(self): self._metrices['funCalls'] += 1 def cat_pics(self): self._metrices['catPictures_served'] += 1 

Am definit două metode noi - increment() și cat_pics(). Am modificat valorile folosind aceste funcții în dict matrice. Aici, putem schimba clasa la fel cum modificăm indicatorul.

 pt = Pointer() pt.increment() pt.increment() pt.funCalls() 

Modulul Python ctypes

Modulul Python ctypes ne permite să creăm un pointer de tip C în Python. Acest modul este util dacă vrem să facem un apel de funcție la o bibliotecă C care necesită un pointer. Să înțelegem următorul exemplu.

Exemplu - Limbajul C

 void incr_one(int *x) { *x += 1; } 

În funcția de mai sus, am crescut valoarea lui x cu unu. Să presupunem că salvăm fișierul de mai sus numit incrPointer.c și tastați următoarea comandă în terminal.

 $ gcc -c -Wall -Werror -fpic incrPointer.c $ gcc -shared -o libinc.so incrPointer.o 

Prima comandă se compilează incrPointer.c într-un obiect numit incrPointer.o. A doua comandă acceptă fișierul obiect și produce libinic.so pentru a colabora cu ctypes.

rune în powershell
 import ctypes ## libinc.so library should be same directory as this program lib = ctypes.CDLL('./libinc.so') lib.increment 

Ieșire:

 

În codul de mai sus, ctypes.CDLL returnează un obiect partajat numit libinic.deci. Acesta conține incrPointer() funcţie. Dacă trebuie să specificăm indicatorul către funcțiile pe care le definim într-un obiect partajat, trebuie să-l specificăm folosind ctypes. Să vedem exemplul de mai jos.

 inc = lib.increment ## defining the argtypes inc.argtypes = [ctypes.POINTER(ctypes.c_int)] 

Dacă apelăm funcția folosind un alt tip, aceasta va fi printr-o eroare.

 incrPointer(10) 

Ieșire:

Traceback (most recent call last): File '', line 1, in ctypes.ArgumentError: argument 1: : expected LP_c_int instance instead of int 

Acest lucru se datorează faptului că incrPointer necesită un pointer și ctypes este o modalitate de a trece pointer în Python.

 v = ctypes.c_int(10) 

v este o variabilă C. Ctypes furnizează metoda numită byref() care trecea referința variabilă.

 inc(ctypes.byref(a)) a 

Ieșire:

c_int(11) 

Am mărit valoarea utilizând variabila de referință.

Concluzie

Am discutat că pointerul nu este prezent în Python, dar putem implementa același comportament cu obiectul *mutable. Am discutat, de asemenea, modulele ctypes care pot defini pointerul C în Python. Am definit câteva moduri excelente de a simula pointerul în Python.