logo

Pointer i Python | Hvorfor Python ikke understøtter pointer

I denne tutorial lærer vi om pointer i Python og se hvorfor Python ikke understøtter pointer-koncepter.

Vi vil også forstå, hvordan vi kan simulere markøren i Python. Nedenfor er introduktionen af ​​pointeren til dem, der ikke har noget om det.

Vi vil også forstå, hvordan vi kan simulere markøren i Python. Nedenfor er introduktionen af ​​pointer for dem, der ikke har noget om det.

Hvad er Pointer?

Pointer er et meget populært og nyttigt værktøj til at gemme variablens adresse. Hvis nogen nogensinde har arbejdet med et sprog på lavt niveau som f.eks C . C++ , ville han/hun sandsynligvis være bekendt med pointers. Det administrerer koden meget effektivt. Det kan være lidt hårdt for begyndere, men det er et af programmets vigtige koncept. Det kan dog føre til forskellige hukommelseshåndteringsfejl. Definitionen af ​​pointere -

'Pegere er de variable, der holder hukommelsesadressen for en anden variabel. Pointervariabler er repræsenteret med en stjerne (*).'

Lad os se følgende eksempel på markøren i programmeringssproget C.

Eksempel - Sådan bruger du pointer i 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; } 

Produktion:

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 

Udover at være nyttige, bruges pointere ikke i Python . I dette emne vil vi diskutere Pythons objektmodel og lære hvorfor pointere i Python ikke eksisterer. Vi vil også lære forskellige måder at simulere pointere i Python. Lad os først diskutere, hvorfor Python ikke understøtter Pointers.

Hvorfor understøtter Python ikke pointere

Den nøjagtige årsag til ikke at understøtte markøren er ikke klar. Kunne pointer i Python eksistere indbygget? Hovedkonceptet for Python er dets enkelhed, men pointeren overtrådte Zen af ​​Python. Pointers tilskyndes hovedsageligt til implicitte ændringer i stedet for eksplicitte. De er også komplekse, især for begyndere.

Pointere har en tendens til at skabe kompleksitet i koden, hvor Python primært fokuserer på brugervenlighed frem for hastighed. Som et resultat understøtter Python ikke pointer. Python giver dog nogle fordele ved at bruge markøren.

Før vi forstår pointeren i Python, skal vi have den grundlæggende idé om følgende punkter.

  • Uforanderlige vs. foranderlige objekter
  • Python variabler/navne

Objekter i Python

I Python er alt et objekt, selv klasse, funktioner, variabler osv. Hvert objekt indeholder mindst tre stykker data.

java-forbindelse
  • Referenceantal
  • Type
  • Værdi

Lad os diskutere en efter en.

Referenceantal - Det bruges til hukommelsesstyring. For at få flere oplysninger om Python-hukommelseshåndtering, læs Memory Management i Python.

Type - Det CPython lag bruges som typen for at sikre typesikkerhed under kørsel. Til sidst er der en værdi, som er den faktiske værdi forbundet med objektet.

Hvis vi går i dybden i dette objekt, vil vi dog opdage, at ikke alle objekter er ens. Den vigtige skelnen mellem objekttyperne er uforanderlig og foranderlig. Først og fremmest skal vi forstå forskellen mellem objekttyperne, fordi det udforsker markøren i Python.

Uforanderlige vs. Foranderlige objekter

Uforanderlige objekter kan ikke ændres, hvor foranderlige objekter kan ændres. Lad os se følgende tabel over almindelige typer, og om de kan ændres eller ej.

Objekter Type
Int Uforanderlig
Flyde Uforanderlig
Bool Uforanderlig
Liste Foranderlig
Sæt Foranderlig
Kompleks Foranderlig
Tuple Uforanderlig
Frozenset Uforanderlig
Dict Foranderlig

Vi kan kontrollere typen af ​​ovenstående objekter ved hjælp af id() metode. Denne metode returnerer objektets hukommelsesadresse.

Vi skriver nedenstående linjer i et REPL-miljø.

hjemmeside som coomeet
 x = 5 id(x) 

Produktion:

140720979625920 

I ovenstående kode har vi tildelt værdien 10 til x. hvis vi ændrede denne værdi med substitution, ville vi få de nye objekter.

 x-=1 id(x) 

Produktion:

140720979625888 

Som vi kan se, ændrer vi ovenstående kode og får nye objekter som et svar. Lad os tage et andet eksempel på str .

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

Produktion:

2315970974512 JavaTpoint 1977728175088 

Igen ændrer vi værdien af ​​x ved at tilføje en ny streng, og vi får den nye hukommelsesadresse. Lad os prøve at tilføje streng direkte i s.

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

Produktion:

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 

Ovenstående kode returnerer fejl, det betyder, at strengen ikke understøtter mutationen. Så str er de uforanderlige objekter.

Nu vil vi se det foranderlige objekt såsom liste.

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

Produktion:

2571132658944 [3, 4, 8, 4] 2571132658944 

Som vi kan se i ovenstående kode, er min_liste har id'et oprindeligt, og vi har tilføjet 5 til listen; min_liste har samme id, fordi listen understøtter foranderlighed.

Forstå Python-variabler

Måden at definere variable på i Python er meget anderledes end C eller C++. Python-variablen definerer ikke datatypen. Faktisk har Python navne, ikke variable.

Så vi er nødt til at forstå forskellen mellem variabler og navne og især sandt, når vi navigerer i det vanskelige emne med pointere i Python.

Lad os forstå, hvordan variablen fungerer i C, og hvordan navnet fungerer i Python.

Variabler i C

I C-sprog er en variabel, at den har værdi eller butiksværdi. Det er defineret med datatypen. Lad os se følgende kode, der definerer variablen.

 int x = 286; 
  • Tildel nok hukommelse til et heltal.
  • Vi tildeler værdien 286 til denne hukommelsesplacering.
  • X repræsenterer denne værdi.

Hvis vi repræsenterer synet på hukommelsen -

Pointer i Python

Som vi kan se, har x en hukommelsesplacering for værdien 286. Nu vil vi tildele den nye værdi til x.

x = 250

Denne nye værdi overskriver den tidligere værdi. Det betyder, at variablen x kan ændres.

Værdien placeringen af ​​x er den samme, men værdien ændret. Det er et væsentligt punkt, der indikerer, at x er hukommelsesplaceringen, ikke kun dens navn.

Nu introducerer vi den nye variabel, der tager x, og derefter opretter y den nye hukommelsesboks.

streng concat java
 int y = x; 

Variablen y opretter en ny boks kaldet y kopierer værdien af ​​fra x ind i boksen.

Pointer i Python

Navne i Python

Som vi diskuterede tidligere har Python ikke variablerne. Det har navne, og vi bruger dette udtryk som variable. Men der er forskel på variabler og navne. Lad os se følgende eksempel.

 x = 289 

Ovenstående kode er opdelt under udførelse.

  1. Opret et PyObject
  2. Indstil typekoden til heltal for PyObject
  3. Indstil værdien til 289 for PyObject
  4. Opret et navn kaldet x
  5. Peg x til det nye PyObject
  6. Øg gentællingen af ​​PyObject med 1

Det vil se ud som nedenfor.

Pointer i Python

Vi kan forstå den interne funktion af en variabel i Python. Variablen x peger på objektets reference, og den har ikke hukommelsespladsen som før. Det viser også, at x = 289 binder navnet x til en reference.

Nu introducerer vi en ny variabel og tildeler den x.

 y = x 

I Python vil variablen y ikke skabe det nye objekt; det er bare et nyt navn, der peger på det samme objekt. Objektet gentælle også steget med én. Vi kan bekræfte det som følger.

 y is x 

Produktion:

True 

Hvis vi øger værdien af ​​y med én, vil det ikke længere referere til det samme objekt.

 y + =1 y is x 

Det betyder, at vi i Python ikke tildeler variabler. I stedet binder vi navne til reference.

Simulering af pointere i Python

Som vi har diskuteret, understøtter Python ikke pointer, men vi kan få fordelene ved at bruge en pointer. Python giver alternative måder at bruge markøren på i Python. Disse to måder er angivet nedenfor.

  • Brug af mutable typer som pointer
  • Brug af brugerdefinerede Python-objekter

Lad os forstå de givne punkter.

Brug af foranderlige typer som markør

I det foregående afsnit har vi defineret de mutable type objekter; vi kan behandle dem, som om de var pointere til at simulere pointers adfærd. Lad os forstå følgende eksempel.

C

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

I ovenstående kode definerede vi pointer *a, så øger vi værdien med én. Nu vil vi implementere det med funktionen main().

sara ali khan alder
 #include int main(void) { int y = 233; printf('y = %d
', y); add_one(&y); printf('y = %d
', y); return 0; } 

Produktion:

y = 233 y = 234 

Vi kan simulere denne type adfærd ved at bruge den mutable Python-type. Forstå følgende eksempel.

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

Ovenstående funktion får adgang til det første element i listen og øger dets værdi med én. Når vi udfører ovenstående program, udskriver det den ændrede værdi af y. Det betyder, at vi kan replikere markøren ved hjælp af det mutable objekt. Men hvis vi forsøger at simulere pointer ved hjælp af uforanderligt objekt.

 z = (2337,) add_one(z) 

Produktion:

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

Vi brugte tuple i ovenstående kode, et uforanderligt objekt, så det returnerede fejlen. Vi kan også bruge ordbogen til at simulere markøren i Python.

Lad os forstå følgende eksempel, hvor vi vil tælle hver operation, der forekommer i programmet. Vi kan bruge diktat til at opnå dette.

Eksempel -

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

Produktion:

2 

Forklaring -

I ovenstående eksempel har vi brugt tælle ordbog, som holdt styr på antallet af funktionskald. Når foo() funktionen kaldes, øges tælleren 2, fordi dict kan ændres.

Brug af Python-objekter

I det foregående eksempel har vi brugt dict til at efterligne markøren i Python, men nogle gange bliver det svært at huske alle brugte nøglenavne. Vi kan bruge den tilpassede Python-klasse i stedet for ordbogen. Lad os forstå følgende eksempel.

Eksempel -

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

I ovenstående kode har vi defineret Pointer-klassen. Denne klasse brugte dict til at holde faktiske data i medlemsvariablen _metrics. Det vil give foranderlighed til vores program. Vi kan gøre dette som følger.

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

Vi har brugt @ejendom dekoratør. Hvis du ikke er bekendt med dekoratører, kan du besøge vores Python-dekorationsvejledning. @property-dekoratøren får adgang til funCalls og catPicture_served. Nu vil vi oprette et objekt af klassen Pointer.

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

Her skal vi øge disse værdier.

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

Vi har defineret to nye metoder - increment() og cat_pics(). Vi har ændret værdierne ved hjælp af disse funktioner i matricerne dict. Her kan vi ændre klassen på samme måde, som vi ændrer markøren.

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

Python ctypes modul

Python ctypes modul giver os mulighed for at oprette en C-type pointer i Python. Dette modul er nyttigt, hvis vi ønsker at foretage et funktionskald til et C-bibliotek, der kræver en pointer. Lad os forstå følgende eksempel.

Eksempel - C Sprog

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

I ovenstående funktion har vi øget værdien af ​​x med én. Antag, at vi gemmer ovenstående fil med navnet incrPointer.c og skriv følgende kommando i terminalen.

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

Den første kommando kompilerer incrPointer.c ind i et objekt kaldet incrPointer.o. Den anden kommando accepterer objektfil og producerer libinic.so til at samarbejde med ctypes.

ulv eller ræv
 import ctypes ## libinc.so library should be same directory as this program lib = ctypes.CDLL('./libinc.so') lib.increment 

Produktion:

 

I ovenstående kode er ctypes.CDLL returnerer et delt objekt kaldet libinisk.så. Den indeholder incrPointer() fungere. Hvis vi skal angive markøren til de funktioner, vi definerer i et delt objekt, skal vi angive det ved hjælp af ctypes. Lad os se nedenstående eksempel.

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

Hvis vi kalder funktionen ved hjælp af en anden type, vil den gennem en fejl.

 incrPointer(10) 

Produktion:

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

Dette skyldes, at incrPointer kræver en pointer og ctypes er en måde at sende pointer i Python.

 v = ctypes.c_int(10) 

v er en C-variabel. ctypes giver metoden kaldet byref() som plejede at videregive variabelreferencen.

 inc(ctypes.byref(a)) a 

Produktion:

c_int(11) 

Vi har øget værdien ved hjælp af referencevariablen.

Konklusion

Vi har diskuteret, at pointer ikke er til stede i Python, men vi kan implementere den samme adfærd med det *mutable objekt. Vi diskuterede også ctypes-modulerne, der kan definere C pointer i Python. Vi har defineret et par fremragende måder at simulere pointer i Python.