logo

Peker i Python | Hvorfor Python ikke støtter peker

I denne opplæringen vil vi lære om peker i Python og se hvorfor Python ikke støtter pekerkonsepter.

Vi vil også forstå hvordan vi kan simulere pekeren i Python. Nedenfor er introduksjonen av pekeren for de som ikke har noe om det.

Vi vil også forstå hvordan vi kan simulere pekeren i Python. Nedenfor er introduksjonen av pekeren for de som ikke har noe om det.

Hva er Pointer?

Peker er et veldig populært og nyttig verktøy for å lagre adressen til variabelen. Hvis noen noen gang har jobbet med et lavnivåspråk som f.eks C . C++ , ville han/hun sannsynligvis være kjent med pekere. Den administrerer koden veldig effektivt. Det kan være litt tøft for nybegynnere, men det er et av de viktigste konseptene i programmet. Det kan imidlertid føre til forskjellige minnehåndteringsfeil. Dermed er definisjonen av pekere -

'Pekere er variablene som holder minneadressen til en annen variabel. Pekervariabler er representert med stjerne (*).'

La oss se følgende eksempel på pekeren i programmeringsspråket C.

Eksempel - Hvordan bruke peker 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; } 

Produksjon:

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 

I tillegg til å være nyttige, brukes ikke pekere i Python . I dette emnet vil vi diskutere Pythons objektmodell og lære hvorfor pekere i Python ikke eksisterer. Vi vil også lære ulike måter å simulere pekere i Python. La oss først diskutere hvorfor Python ikke støtter Pointers.

Hvorfor støtter ikke Python pekere

Den nøyaktige årsaken til at pekeren ikke støttes er ikke klar. Kan pekeren i Python eksistere naturlig? Hovedkonseptet til Python er dets enkelhet, men pekeren brøt med Zen fra Python. Pekere oppfordres hovedsakelig til implisitte endringer i stedet for eksplisitte. De er også komplekse, spesielt for nybegynnere.

Pekere har en tendens til å skape kompleksitet i koden, der Python hovedsakelig fokuserer på brukervennlighet fremfor hastighet. Som et resultat støtter ikke Python peker. Python gir imidlertid noen fordeler med å bruke pekeren.

Før vi forstår pekeren i Python, må vi ha den grunnleggende ideen om følgende punkter.

  • Uforanderlige vs. foranderlige objekter
  • Python-variabler/navn

Objekter i Python

I Python er alt et objekt, til og med klasse, funksjoner, variabler osv. Hvert objekt inneholder minst tre databiter.

java-tilkobling
  • Referansetelling
  • Type
  • Verdi

La oss diskutere en etter en.

Referansetall - Den brukes til minnebehandling. For å få mer informasjon om Python-minneadministrasjon, les Memory Management i Python.

Type - De CPython lag brukes som type for å sikre typesikkerhet under kjøretid. Til slutt er det en verdi, som er den faktiske verdien knyttet til objektet.

Hvis vi går i dybden i dette objektet, vil vi finne at ikke alle objekter er like. Det viktige skillet mellom objekttypene er uforanderlig og foranderlig. Først av alt må vi forstå forskjellen mellom objekttypene fordi den utforsker pekeren i Python.

Uforanderlige vs. Mulige objekter

Uforanderlige objekter kan ikke endres, der foranderlige objekter kan endres. La oss se følgende tabell over vanlige typer og om de kan endres eller ikke.

Objekter Type
Int Uforanderlig
Flyte Uforanderlig
Bool Uforanderlig
Liste Mulig
Sett Mulig
Kompleks Mulig
Tuppel Uforanderlig
Frossensett Uforanderlig
Dict Mulig

Vi kan sjekke typen av objektene ovenfor ved å bruke id() metode. Denne metoden returnerer objektets minneadresse.

Vi skriver inn linjene nedenfor i et REPL-miljø.

linux snarveier
 x = 5 id(x) 

Produksjon:

140720979625920 

I koden ovenfor har vi tildelt verdien 10 til x. hvis vi modifiserte denne verdien med substitusjon, ville vi fått de nye objektene.

 x-=1 id(x) 

Produksjon:

140720979625888 

Som vi kan se, modifiserer vi koden ovenfor og får nye objekter som svar. La oss ta et annet eksempel på str .

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

Produksjon:

2315970974512 JavaTpoint 1977728175088 

Igjen endrer vi verdien av x ved å legge til en ny streng, og vi får den nye minneadressen. La oss prøve å legge til streng direkte i s.

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

Produksjon:

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 

Koden ovenfor returnerer feil, det betyr at strengen ikke støtter mutasjonen. Så str er de uforanderlige objektene.

Nå vil vi se det foranderlige objektet som liste.

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

Produksjon:

2571132658944 [3, 4, 8, 4] 2571132658944 

Som vi kan se i koden ovenfor, er min liste har id opprinnelig, og vi har lagt til med 5 til listen; min liste har samme ID fordi listen støtter foranderlighet.

Forstå Python-variabler

Måten å definere variabler på i Python er mye annerledes enn C eller C++. Python-variabelen definerer ikke datatypen. Faktisk har Python navn, ikke variabler.

Så vi må forstå forskjellen mellom variabler og navn, og spesielt sant når vi navigerer i det vanskelige emnet med pekere i Python.

La oss forstå hvordan variabelen fungerer i C og hvordan navnet fungerer i Python.

Variabler i C

I C-språk er en variabel at den har verdi eller lagreverdi. Det er definert med datatypen. La oss se følgende kode som definerer variabelen.

 int x = 286; 
  • Tildel nok minne for et heltall.
  • Vi tildeler verdien 286 til den minneplasseringen.
  • x-en representerer denne verdien.

Hvis vi representerer synet på minne -

Peker i Python

Som vi kan se, har x en minneplassering for verdien 286. Nå vil vi tilordne den nye verdien til x.

x = 250

Denne nye verdien overskriver den forrige verdien. Det betyr at variabelen x er mutbar.

Verdiplasseringen til x er den samme, men verdien endret. Det er et viktig poeng som indikerer at x er minneplasseringen, ikke bare navnet.

Nå introduserer vi den nye variabelen som tar x, så lager y den nye minneboksen.

fjær mvc
 int y = x; 

Variabelen y oppretter en ny boks kalt y kopierer verdien av fra x inn i boksen.

Peker i Python

Navn i Python

Som vi diskuterte tidligere har ikke Python variablene. Den har navn, og vi bruker dette begrepet som variabler. Men det er forskjell på variabler og navn. La oss se følgende eksempel.

 x = 289 

Koden ovenfor brytes ned under kjøring.

  1. Lag et PyObject
  2. Sett typekoden til heltall for PyObject
  3. Sett verdien til 289 for PyObject
  4. Lag et navn kalt x
  5. Pek x til det nye PyObject
  6. Øk gjentellingen til PyObject med 1

Det vil se ut som nedenfor.

Peker i Python

Vi kan forstå den interne funksjonen til en variabel i Python. Variabelen x peker på referansen til objektet, og den har ikke minneplassen som før. Den viser også at x = 289 binder navnet x til en referanse.

Nå introduserer vi ny variabel og tildeler x til den.

 y = x 

I Python vil ikke variabelen y lage det nye objektet; det er bare et nytt navn som peker på det samme objektet. Objektet telle på nytt også økt med én. Vi kan bekrefte det som følger.

 y is x 

Produksjon:

True 

Hvis vi øker verdien av y med én, vil den ikke lenger referere til det samme objektet.

 y + =1 y is x 

Det betyr at vi i Python ikke tildeler variabler. I stedet binder vi navn til referanse.

Simulering av pekere i Python

Som vi har diskutert, støtter ikke Python peker, men vi kan få fordelene ved å bruke en peker. Python gir alternative måter å bruke pekeren i Python. Disse to måtene er gitt nedenfor.

  • Bruke mutable typer som pekere
  • Bruke tilpassede Python-objekter

La oss forstå de gitte punktene.

Bruke foranderlige typer som peker

I forrige seksjon har vi definert objekter av mutable type; vi kan behandle dem som om de var pekere for å simulere pekeratferd. La oss forstå følgende eksempel.

C

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

I koden ovenfor definerte vi pekeren *a, så øker vi verdien med én. Nå skal vi implementere det med main()-funksjonen.

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

Produksjon:

y = 233 y = 234 

Vi kan simulere denne typen atferd ved å bruke den mutable Python-typen. Forstå følgende eksempel.

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

Funksjonen ovenfor får tilgang til det første elementet i listen og øker verdien med én. Når vi kjører programmet ovenfor, skriver det ut den modifiserte verdien av y. Det betyr at vi kan replikere pekeren ved å bruke det mutbare objektet. Men hvis vi prøver å simulere pekeren ved hjelp av uforanderlig objekt.

 z = (2337,) add_one(z) 

Produksjon:

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

Vi brukte tuppelen i koden ovenfor, et uforanderlig objekt, så det returnerte feilen. Vi kan også bruke ordboken til å simulere pekeren i Python.

La oss forstå følgende eksempel der vi vil telle hver operasjon som skjer i programmet. Vi kan bruke dikt for å oppnå dette.

Eksempel -

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

Produksjon:

2 

Forklaring -

I eksemplet ovenfor har vi brukt telle ordbok, som holdt styr på antall funksjonsanrop. Når foo() funksjonen kalles, økes telleren 2 fordi dict kan endres.

Bruke Python-objekter

I forrige eksempel har vi brukt dict for å emulere pekeren i Python, men noen ganger blir det vanskelig å huske alle brukte nøkkelnavn. Vi kan bruke den tilpassede Python-klassen i stedet for ordboken. La oss forstå følgende eksempel.

Eksempel -

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

I koden ovenfor har vi definert Pointer-klassen. Denne klassen brukte dict for å holde faktiske data i medlemsvariabelen _metrics. Det vil gi foranderlighet til programmet vårt. Vi kan gjø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 brukt @eiendom dekoratør. Hvis du ikke er kjent med dekoratører, besøk vår Python-dekorasjonsveiledning. @property-dekoratøren vil få tilgang til funCalls og catPicture_served. Nå skal vi lage et objekt av Pointer-klassen.

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

Her må vi øke disse verdiene.

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

Vi har definert to nye metoder - increment(), og cat_pics(). Vi har modifisert verdiene ved å bruke disse funksjonene i matrisene dict. Her kan vi endre klassen på samme måte som vi endrer pekeren.

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

Python ctypes-modul

Python ctypes-modulen lar oss lage en C-type-peker i Python. Denne modulen er nyttig hvis vi ønsker å foreta et funksjonskall til et C-bibliotek som krever en peker. La oss forstå følgende eksempel.

Eksempel - C Språk

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

I funksjonen ovenfor har vi økt verdien av x med én. Anta at vi lagrer filen over kalt 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 kommandoen kompileres incrPointer.c inn i et objekt kalt incrPointer.o. Den andre kommandoen godtar objektfil og produsere libinic.so for å samarbeide med ctypes.

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

Produksjon:

 

I koden ovenfor er det ctypes.CDLL returnerer et delt objekt kalt libinic.so. Den inneholder incrPointer() funksjon. Hvis vi trenger å spesifisere pekeren til funksjonene vi definerer i et delt objekt, må vi spesifisere det ved hjelp av ctypes. La oss se eksemplet nedenfor.

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

Hvis vi kaller funksjonen med en annen type, vil den gjennom en feil.

 incrPointer(10) 

Produksjon:

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

Dette er fordi incrPointer krever en peker og ctypes er en måte å sende peker i Python.

 v = ctypes.c_int(10) 

v er en C-variabel. Ctypes gir metoden kalt byref() som pleide å sende variabelreferansen.

 inc(ctypes.byref(a)) a 

Produksjon:

c_int(11) 

Vi har økt verdien ved å bruke referansevariabelen.

Konklusjon

Vi har diskutert at pekeren ikke er tilstede i Python, men vi kan implementere den samme oppførselen med det *mutable objektet. Vi diskuterte også ctypes-modulene som kan definere C-pekeren i Python. Vi har definert noen få utmerkede måter å simulere peker i Python.