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 -
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.
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.
- Opret et PyObject
- Indstil typekoden til heltal for PyObject
- Indstil værdien til 289 for PyObject
- Opret et navn kaldet x
- Peg x til det nye PyObject
- Øg gentællingen af PyObject med 1
Det vil se ud som nedenfor.
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.