I den här handledningen kommer vi att lära oss om pekare i Python och se varför Python inte stöder pekarkoncept.
Vi kommer också att förstå hur vi kan simulera pekaren i Python. Nedan är introduktionen av pekaren för de som inte har något om det.
Vi kommer också att förstå hur vi kan simulera pekaren i Python. Nedan är introduktionen av pekaren för de som inte har något om det.
Vad är Pointer?
Pointer är ett mycket populärt och användbart verktyg för att lagra adressen till variabeln. Om någon någon gång jobbat med ett lågnivåspråk som t.ex C . C++ , han/hon skulle förmodligen vara bekant med pekare. Den hanterar koden mycket effektivt. Det kan vara lite tufft för nybörjare, men det är ett av programmets viktiga koncept. Det kan dock leda till olika minneshanteringsbuggar. Således definitionen av pekare -
'Pekare är variablerna som håller minnesadressen för en annan variabel. Pekarvariabler representeras av asterisk (*).'
Låt oss se följande exempel på pekaren i programmeringsspråket C.
Exempel - Hur man använder pekaren 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
Förutom att vara användbara används inte pekare i Pytonorm . I det här ämnet kommer vi att diskutera Pythons objektmodell och lära oss varför pekare i Python inte finns. Vi kommer också att lära oss olika sätt att simulera pekare i Python. Låt oss först diskutera varför Python inte stöder Pointers.
Varför stöder inte Python pekare
Den exakta orsaken till att inte stödja pekaren är inte klar. Kan pekare i Python existera inbyggt? Huvudkonceptet för Python är dess enkelhet, men pekaren bröt mot Zen av Python. Pekare uppmuntras främst implicita förändringar snarare än explicita. De är också komplexa, särskilt för nybörjare.
Pekare tenderar att skapa komplexitet i koden, där Python främst fokuserar på användbarhet snarare än hastighet. Som ett resultat har Python inte stöd för pekare. Python ger dock vissa fördelar med att använda pekaren.
Innan vi förstår pekaren i Python måste vi ha grundidén för följande punkter.
- Oföränderliga vs. föränderliga objekt
- Python-variabler/namn
Objekt i Python
I Python är allt ett objekt, även klass, funktioner, variabler etc. Varje objekt innehåller minst tre datastycken.
java färger
- Referensräkning
- Typ
- Värde
Låt oss diskutera en efter en.
Antal referenser - Den används för minneshantering. För att få mer information om Python-minneshantering, läs Minneshantering i Python.
Typ - De CPython lager används som typ för att säkerställa typsäkerhet under körning. Slutligen finns det ett värde, som är det faktiska värdet som är associerat med objektet.
Om vi går på djupet i det här objektet kommer vi dock att upptäcka att inte alla objekt är likadana. Den viktiga skillnaden mellan typerna av objekt är oföränderlig och föränderlig. Först och främst måste vi förstå skillnaden mellan typerna av objekt eftersom det utforskar pekaren i Python.
Oföränderliga vs. föränderliga objekt
Oföränderliga objekt kan inte modifieras, där föränderliga objekt kan modifieras. Låt oss se följande tabell över vanliga typer och om de är föränderliga eller inte.
Föremål | Typ |
---|---|
Int | Oföränderlig |
Flyta | Oföränderlig |
Bool | Oföränderlig |
Lista | Föränderlig |
Uppsättning | Föränderlig |
Komplex | Föränderlig |
Tuple | Oföränderlig |
Frozenset | Oföränderlig |
Dict | Föränderlig |
Vi kan kontrollera typen av ovanstående objekt med hjälp av id() metod. Denna metod returnerar objektets minnesadress.
Vi skriver raderna nedan i en REPL-miljö.
x = 5 id(x)
Produktion:
140720979625920
I koden ovan har vi tilldelat värdet 10 till x. om vi modifierade detta värde med substitution skulle vi få de nya objekten.
x-=1 id(x)
Produktion:
140720979625888
Som vi kan se modifierar vi ovanstående kod och får nya objekt som ett svar. Låt oss ta ett annat exempel på str .
s = 'java' print(id(s)) s += 'Tpoint' print(s) id(s)
Produktion:
2315970974512 JavaTpoint 1977728175088
Återigen ändrar vi värdet på x genom att lägga till en ny sträng, och vi får den nya minnesadressen. Låt oss försöka lägga till sträng direkt 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
Ovanstående kod returnerar fel, det betyder att strängen inte stöder mutationen. Så str är de oföränderliga objekten.
Nu kommer vi att se det föränderliga objektet som listan.
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 ovanstående kod är min lista har id ursprungligen, och vi har lagt till med 5 till listan; min lista har samma id eftersom listan stöder föränderlighet.
Förstå Python-variabler
Sättet att definiera variabler i Python är mycket annorlunda än C eller C++. Python-variabeln definierar inte datatypen. Faktum är att Python har namn, inte variabler.
vad betyder xdxd
Så vi måste förstå skillnaden mellan variabler och namn och särskilt sant när vi navigerar i det knepiga ämnet pekare i Python.
Låt oss förstå hur variabeln fungerar i C och hur namnet fungerar i Python.
Variabler i C
I C-språket är en variabel att den har värde eller lagra värde. Den definieras med datatypen. Låt oss se följande kod som definierar variabeln.
int x = 286;
- Tilldela tillräckligt med minne för ett heltal.
- Vi tilldelar värdet 286 till den minnesplatsen.
- X representerar det värdet.
Om vi representerar synen på minnet -
Som vi kan se har x en minnesplats för värdet 286. Nu kommer vi att tilldela det nya värdet till x.
x = 250
Detta nya värde skriver över det tidigare värdet. Det betyder att variabeln x är föränderlig.
Värdeplatsen för x är densamma, men värdet har ändrats. Det är en viktig punkt som indikerar att x är minnesplatsen, inte bara dess namn.
Nu introducerar vi den nya variabeln som tar x, sedan skapar y den nya minnesrutan.
int y = x;
Variabeln y skapar en ny ruta som heter y kopierar värdet på från x till rutan.
Namn i Python
Som vi diskuterade tidigare har Python inte variablerna. Den har namn, och vi använder denna term som variabler. Men det är skillnad på variabler och namn. Låt oss se följande exempel.
x = 289
Ovanstående kod bryts ner under körning.
- Skapa ett PyObject
- Ställ in typkoden på heltal för PyObject
- Ställ in värdet på 289 för PyObject
- Skapa ett namn som heter x
- Peka x till det nya PyObject
- Öka återräkningen av PyObject med 1
Det kommer att se ut som nedan.
Vi kan förstå hur en variabel fungerar internt i Python. Variabeln x pekar på objektets referens och den har inte minnesutrymmet som tidigare. Det visar också att x = 289 binder namnet x till en referens.
Nu introducerar vi en ny variabel och tilldelar den x.
y = x
I Python kommer variabeln y inte att skapa det nya objektet; det är bara ett nytt namn som pekar på samma objekt. Objektet återräkning också ökat med ett. Vi kan bekräfta det enligt följande.
metoder i java
y is x
Produktion:
True
Om vi ökar värdet på y med ett kommer det inte längre att referera till samma objekt.
y + =1 y is x
Det betyder att vi i Python inte tilldelar variabler. Istället binder vi namn till referenser.
Simulera pekare i Python
Som vi har diskuterat stöder Python inte pekare, men vi kan få fördelarna med att använda en pekare. Python tillhandahåller alternativa sätt att använda pekaren i Python. Dessa två sätt ges nedan.
- Använder föränderliga typer som pekare
- Använda anpassade Python-objekt
Låt oss förstå de givna punkterna.
Använda föränderliga typer som pekare
I det föregående avsnittet har vi definierat de föränderliga objekten; vi kan behandla dem som om de vore pekare för att simulera pekarens beteende. Låt oss förstå följande exempel.
C
void add_one(int *a) { *a += 1; }
I koden ovan definierade vi pekaren *a, sedan ökar vi värdet med ett. Nu kommer vi att implementera det med funktionen main().
np prick
#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 simulera den här typen av beteende genom att använda den föränderliga Python-typen. Förstå följande exempel.
def add_one(x): x[0] += 1 y = [2337] add_one(y) y[0]
Ovanstående funktion kommer åt det första elementet i listan och ökar dess värde med ett. När vi kör programmet ovan skrivs det modifierade värdet av y ut. Det betyder att vi kan replikera pekaren med det föränderliga objektet. Men om vi försöker simulera pekaren med ett oföränderligt 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 använde tupeln i ovanstående kod, ett oföränderligt objekt, så det returnerade felet. Vi kan också använda ordboken för att simulera pekaren i Python.
Låt oss förstå följande exempel där vi kommer att räkna varje operation som sker i programmet. Vi kan använda dikt för att uppnå detta.
Exempel -
count = {'funcCalls': 0} def car(): count['funcCalls'] += 1 def foo(): count['funCcalls'] += 1 car() foo() count['funcCalls']
Produktion:
2
Förklaring -
I exemplet ovan har vi använt räkna ordbok, som höll reda på antalet funktionsanrop. När foo() funktionen anropas, räknaren ökas 2 eftersom dict är föränderligt.
Använda Python-objekt
I föregående exempel har vi använt dict för att emulera pekaren i Python, men ibland blir det svårt att komma ihåg alla använda nyckelnamn. Vi kan använda den anpassade klassen Python i stället för ordboken. Låt oss förstå följande exempel.
Exempel -
class Pointer(object): def __init__(self): self._metrics = { 'funCalls': 0, 'catPictures': 0, }
I ovanstående kod har vi definierat klassen Pointer. Den här klassen använde dict för att hålla faktiska data i medlemsvariabeln _metrics. Det kommer att ge förändringar i vårt program. Vi kan göra detta enligt följande.
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 använt @fast egendom dekoratör. Om du inte är bekant med dekoratörer, besök vår Python-dekoratörshandledning. @property-dekoratören kommer åt funCalls och catPicture_served. Nu kommer vi att skapa ett objekt av klassen Pointer.
pt = Pointer() pt.funCalls() pt.catPicture_served
Här måste vi öka dessa värden.
class Pointer(object): # ... def increament(self): self._metrices['funCalls'] += 1 def cat_pics(self): self._metrices['catPictures_served'] += 1
Vi har definierat två nya metoder - increment() och cat_pics(). Vi har modifierat värdena med hjälp av dessa funktioner i matrisen dict. Här kan vi ändra klassen på samma sätt som vi ändrar pekaren.
pt = Pointer() pt.increment() pt.increment() pt.funCalls()
Python ctypes-modul
Python ctypes-modulen låter oss skapa en C-typpekare i Python. Den här modulen är användbar om vi vill göra ett funktionsanrop till ett C-bibliotek som kräver en pekare. Låt oss förstå följande exempel.
Exempel - C Språk
void incr_one(int *x) { *x += 1; }
I ovanstående funktion har vi ökat värdet på x med ett. Anta att vi sparar ovanstående fil med namnet incrPointer.c och skriv följande kommando i terminalen.
$ gcc -c -Wall -Werror -fpic incrPointer.c $ gcc -shared -o libinc.so incrPointer.o
Det första kommandot kompileras incrPointer.c till ett objekt som kallas incrPointer.o. Det andra kommandot accepterar objektfil och producerar libinic.so för att samarbeta med ctypes.
namn på specialtecken
import ctypes ## libinc.so library should be same directory as this program lib = ctypes.CDLL('./libinc.so') lib.increment
Produktion:
I ovanstående kod är ctypes.CDLL returnerar ett delat objekt anropat libinic.so. Den innehåller incrPointer() fungera. Om vi behöver specificera pekaren till de funktioner vi definierar i ett delat objekt, måste vi specificera det med ctypes. Låt oss se exemplet nedan.
inc = lib.increment ## defining the argtypes inc.argtypes = [ctypes.POINTER(ctypes.c_int)]
Om vi anropar funktionen med en annan typ, kommer det genom ett fel.
incrPointer(10)
Produktion:
Traceback (most recent call last): File '', line 1, in ctypes.ArgumentError: argument 1: : expected LP_c_int instance instead of int
Detta beror på att incrPointer kräver en pekare och ctypes är ett sätt att skicka pekare i Python.
v = ctypes.c_int(10)
v är en C-variabel. Ctypes tillhandahåller metoden som kallas byref() som brukade skicka variabelreferensen.
inc(ctypes.byref(a)) a
Produktion:
c_int(11)
Vi har ökat värdet med referensvariabeln.
Slutsats
Vi har diskuterat att pekaren inte finns i Python, men vi kan implementera samma beteende med *mutable-objektet. Vi diskuterade också ctypes-modulerna som kan definiera C-pekaren i Python. Vi har definierat några utmärkta sätt att simulera pekare i Python.