logo

Rādītājs programmā Python | Kāpēc Python neatbalsta rādītāju

Šajā apmācībā mēs uzzināsim par rādītāju Python un uzzināsim, kāpēc Python neatbalsta rādītāju koncepcijas.

Mēs arī sapratīsim, kā mēs varam simulēt rādītāju Python. Tālāk ir sniegts rādītāja ievads tiem, kam par to nekas nav zināms.

Mēs arī sapratīsim, kā mēs varam simulēt rādītāju Python. Tālāk ir sniegts rādītāja ievads tiem, kam par to nekas nav zināms.

Kas ir rādītājs?

Rādītājs ir ļoti populārs un noderīgs rīks mainīgā adreses saglabāšanai. Ja kāds kādreiz ir strādājis ar zema līmeņa valodu, piemēram, C . C++ , viņš/viņa droši vien pārzina norādes. Tas ļoti efektīvi pārvalda kodu. Iesācējiem tas var būt nedaudz grūts, taču tas ir viens no svarīgākajiem programmas jēdzieniem. Tomēr tas var izraisīt dažādas atmiņas pārvaldības kļūdas. Tādējādi rādītāju definīcija -

'Rādītāji ir mainīgie, kas satur cita mainīgā atmiņas adresi. Rādītāja mainīgie ir apzīmēti ar zvaigznīti (*).'

Apskatīsim šādu rādītāja piemēru C programmēšanas valodā.

Piemērs — kā lietot rādītāju 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; } 

Izvade:

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 

Norādes nav noderīgas, bet tajās netiek izmantotas Python . Šajā tēmā mēs apspriedīsim Python objektu modeli un uzzināsim, kāpēc Python norādes nepastāv. Mēs arī iemācīsimies dažādus veidus, kā simulēt norādes programmā Python. Vispirms apspriedīsim, kāpēc Python neatbalsta rādītājus.

Kāpēc Python neatbalsta norādes

Precīzs rādītāja neatbalstīšanas iemesls nav skaidrs. Vai rādītājs Python var pastāvēt sākotnēji? Python galvenais jēdziens ir tā vienkāršība, taču rādītājs pārkāpa Python Zen. Norādes galvenokārt tiek veicinātas netiešas izmaiņas, nevis tiešas izmaiņas. Tie ir arī sarežģīti, īpaši iesācējiem.

Norādes mēdz radīt sarežģītību kodā, kur Python galvenokārt koncentrējas uz lietojamību, nevis ātrumu. Tā rezultātā Python neatbalsta rādītāju. Tomēr Python sniedz dažas rādītāja izmantošanas priekšrocības.

Lai saprastu rādītāju Python, mums ir jābūt šādu punktu pamatidejai.

  • Nemainīgi pret mainīgiem objektiem
  • Python mainīgie/nosaukumi

Objekti Python

Python programmā viss ir objekts, pat klase, funkcijas, mainīgie utt. Katrs objekts satur vismaz trīs datu daļas.

sīklietotne
  • Atsauces skaits
  • Tips
  • Vērtība

Apspriedīsimies pa vienam.

Atsauces skaits — To izmanto atmiņas pārvaldībai. Lai iegūtu papildinformāciju par Python atmiņas pārvaldību, izlasiet rakstu Atmiņas pārvaldība programmā Python.

Tips - The CPython slānis tiek izmantots kā veids, lai nodrošinātu tipa drošību izpildlaika laikā. Visbeidzot, ir vērtība, kas ir faktiskā vērtība, kas saistīta ar objektu.

Ja mēs iedziļināsimies šajā objektā, mēs atklāsim, ka ne visi objekti ir vienādi. Būtiskā atšķirība starp objektu veidiem ir nemainīga un mainīga. Pirmkārt, mums ir jāsaprot atšķirība starp objektu veidiem, jo ​​​​tas pēta rādītāju Python.

Nemainīgi pret mainīgiem objektiem

Nemaināmus objektus nevar modificēt, kur var modificēt mainīgos objektus. Apskatīsim šo tabulu par izplatītākajiem veidiem un to, vai tie ir vai nav maināmi.

Objekti Tips
Int Nemainīgs
Pludiņš Nemainīgs
Bool Nemainīgs
Saraksts Mainīgs
Iestatīt Mainīgs
Komplekss Mainīgs
Tuple Nemainīgs
Frozenset Nemainīgs
Dikts Mainīgs

Mēs varam pārbaudīt iepriekš minēto objektu veidu, izmantojot id() metodi. Šī metode atgriež objekta atmiņas adresi.

Mēs ierakstām tālāk norādītās rindiņas REPL vidē.

 x = 5 id(x) 

Izvade:

140720979625920 

Iepriekš minētajā kodā vērtību 10 esam piešķīruši x. ja mēs modificētu šo vērtību ar aizstāšanu, mēs iegūtu jaunos objektus.

 x-=1 id(x) 

Izvade:

140720979625888 

Kā redzam, mēs modificējam iepriekš minēto kodu un saņemam jaunus objektus kā atbildi. Ņemsim vēl vienu piemēru str .

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

Izvade:

stīgu sadalīšana c++
2315970974512 JavaTpoint 1977728175088 

Atkal mēs modificējam x vērtību, pievienojot jaunu virkni, un mēs iegūstam jauno atmiņas adresi. Mēģināsim pievienot virkni tieši s.

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

Izvade:

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 

Virs kods atgriež kļūdu, tas nozīmē, ka virkne neatbalsta mutāciju. Tātad str ir nemainīgi objekti.

Tagad mēs redzēsim mainīgu objektu, piemēram, sarakstu.

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

Izvade:

2571132658944 [3, 4, 8, 4] 2571132658944 

Kā redzam iepriekš minētajā kodā, mans_saraksts sākotnēji ir id, un mēs sarakstam esam pievienojuši 5; mans_saraksts ir tāds pats ID, jo saraksts atbalsta mainīgums.

Izpratne par Python mainīgajiem

Python mainīgo definēšanas veids daudz atšķiras no C vai C++. Python mainīgais nedefinē datu tipu. Faktiski Python ir nosaukumi, nevis mainīgie.

Tāpēc mums ir jāsaprot atšķirība starp mainīgajiem un nosaukumiem, un jo īpaši, ja mēs pārlūkojam sarežģīto norādes tēmu Python.

Sapratīsim, kā mainīgais darbojas C valodā un kā nosaukums darbojas Python.

Mainīgie C

C valodā mainīgais ir tāds, ka tam ir vērtība vai saglabāta vērtība. Tas ir definēts ar datu tipu. Apskatīsim šādu kodu, kas definē mainīgo.

 int x = 286; 
  • Piešķiriet pietiekami daudz atmiņas veselam skaitlim.
  • Šai atmiņas vietai mēs piešķiram vērtību 286.
  • X apzīmē šo vērtību.

Ja mēs pārstāvam skatījumu uz atmiņu -

Rādītājs programmā Python

Kā redzam, x ir atmiņas vieta vērtībai 286. Tagad mēs piešķirsim jauno vērtību x.

x = 250

Šī jaunā vērtība pārraksta iepriekšējo vērtību. Tas nozīmē, ka mainīgais x ir mainīgs.

X vērtības atrašanās vieta ir tāda pati, bet vērtība ir mainīta. Tas ir nozīmīgs punkts, kas norāda, ka x ir atmiņas vieta, nevis tikai tās nosaukums.

Tagad mēs ieviešam jauno mainīgo, kas aizņem x, pēc tam y izveido jaunu atmiņas lodziņu.

 int y = x; 

Mainīgais y izveido jaunu lodziņu, ko sauc par y, kas kopē vērtību no x lodziņā.

Rādītājs programmā Python

Vārdi Python valodā

Kā mēs iepriekš apspriedām, Python nav mainīgo. Tam ir nosaukumi, un mēs izmantojam šo terminu kā mainīgos. Bet pastāv atšķirība starp mainīgajiem un nosaukumiem. Apskatīsim šādu piemēru.

 x = 289 

Iepriekš minētais kods tiek sadalīts izpildes laikā.

  1. Izveidojiet PyObject
  2. Iestatiet PyObject tipa kodu uz veselu skaitli
  3. Iestatiet PyObject vērtību uz 289
  4. Izveidojiet nosaukumu ar nosaukumu x
  5. Norādiet x uz jauno PyObject
  6. Palieliniet PyObject pārskaitījumu par 1

Tas izskatīsies kā zemāk.

Rādītājs programmā Python

Mēs varam saprast mainīgā lieluma iekšējo darbību Python. Mainīgais x norāda uz objekta atsauci, un tam nav tādas atmiņas vietas kā iepriekš. Tas arī parāda, ka x = 289 saista nosaukumu x ar atsauci.

Tagad mēs ieviešam jaunu mainīgo un piešķiram tam x.

 y = x 

Programmā Python mainīgais y neizveidos jaunu objektu; tas ir tikai jauns nosaukums, kas norāda uz to pašu objektu. Objekts pārskaitīšana arī palielinājās par vienu. Mēs to varam apstiprināt šādi.

 y is x 

Izvade:

True 

Ja mēs palielinām y vērtību par vienu, tas vairs neattieksies uz to pašu objektu.

 y + =1 y is x 

Tas nozīmē, ka programmā Python mēs nepiešķiram mainīgos. Tā vietā mēs saistām nosaukumus ar atsaucēm.

palindroma numurs

Rādītāju simulēšana programmā Python

Kā mēs jau apspriedām, Python neatbalsta rādītāju, taču mēs varam iegūt rādītāja izmantošanas priekšrocības. Python nodrošina alternatīvus veidus, kā izmantot rādītāju Python. Šie divi veidi ir norādīti zemāk.

  • Mainīgu tipu izmantošana kā norādes
  • Pielāgotu Python objektu izmantošana

Sapratīsim dotos punktus.

Mainīgo tipu izmantošana kā rādītājs

Iepriekšējā sadaļā mēs esam definējuši mainīga tipa objektus; mēs varam izturēties pret tiem tā, it kā tie būtu norādes, lai simulētu rādītāja uzvedību. Sapratīsim šādu piemēru.

C

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

Iepriekš minētajā kodā mēs definējām rādītāju *a, pēc tam mēs palielinām vērtību par vienu. Tagad mēs to ieviesīsim ar galveno () funkciju.

neobjektivitāte un dispersija
 #include int main(void) { int y = 233; printf('y = %d
', y); add_one(&y); printf('y = %d
', y); return 0; } 

Izvade:

y = 233 y = 234 

Mēs varam simulēt šāda veida uzvedību, izmantojot Python mainīgo tipu. Izprotiet tālāk sniegto piemēru.

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

Iepriekš minētā funkcija piekļūst pirmajam saraksta elementam un palielina tā vērtību par vienu. Kad mēs izpildām iepriekš minēto programmu, tā izdrukā modificēto y vērtību. Tas nozīmē, ka mēs varam atkārtot rādītāju, izmantojot mainīgo objektu. Bet, ja mēs mēģinām simulēt rādītāju, izmantojot nemainīgu objektu.

 z = (2337,) add_one(z) 

Izvade:

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

Mēs izmantojām iepriekšminētajā kodā esošo kopu, kas ir nemainīgs objekts, tāpēc tas atgrieza kļūdu. Mēs varam arī izmantot vārdnīcu, lai simulētu rādītāju Python.

Sapratīsim šādu piemēru, kur mēs uzskaitīsim katru programmā veikto darbību. Lai to panāktu, mēs varam izmantot diktātu.

Piemērs -

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

Izvade:

2 

Paskaidrojums -

Iepriekš minētajā piemērā mēs esam izmantojuši skaitīt vārdnīca, kas sekoja funkciju izsaukumu skaitam. Kad foo () tiek izsaukta funkcija, skaitītājs tiek palielināts par 2, jo dict ir mainīgs.

Izmantojot Python objektus

Iepriekšējā piemērā mēs izmantojām dict, lai atdarinātu rādītāju Python, taču dažreiz ir grūti atcerēties visus izmantotos taustiņu nosaukumus. Mēs varam izmantot Python pielāgoto klasi vārdnīcas vietā. Sapratīsim šādu piemēru.

Piemērs -

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

Iepriekš minētajā kodā mēs esam definējuši Pointer klasi. Šī klase izmantoja diktātu faktisko datu glabāšanai mainīgajā _metrics. Tas nodrošinās mūsu programmas mainīgumu. Mēs to varam izdarīt šādi.

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

Esam izmantojuši @īpašums dekorators. Ja neesat pazīstams ar dekoratoriem, apmeklējiet mūsu Python dekoratoru pamācību. @īpašuma dekorators piekļūs funCalls un catPicture_served. Tagad mēs izveidosim Pointer klases objektu.

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

Šeit mums ir jāpalielina šīs vērtības.

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

Mēs esam definējuši divas jaunas metodes - increment () un cat_pics (). Mēs esam modificējuši vērtības, izmantojot šīs funkcijas matricu diktātā. Šeit mēs varam mainīt klasi tāpat kā mēs modificējam rādītāju.

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

Python ctypes modulis

Python ctypes modulis ļauj mums izveidot C veida rādītāju Python. Šis modulis ir noderīgs, ja vēlamies veikt funkcijas izsaukumu uz C bibliotēku, kurai nepieciešams rādītājs. Sapratīsim šādu piemēru.

Piemērs - C valoda

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

Iepriekš minētajā funkcijā mēs esam palielinājuši x vērtību par vienu. Pieņemsim, ka mēs terminālī saglabājam iepriekš minēto failu ar nosaukumu incrPointer.c un ierakstiet sekojošo komandu.

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

Pirmā komanda tiek apkopota incrPointer.c objektā, ko sauc incrPointer.o. Otrā komanda pieņem objekta failu un izveido libinic.so, lai sadarbotos ar ctypes.

ipconfig uz Ubuntu
 import ctypes ## libinc.so library should be same directory as this program lib = ctypes.CDLL('./libinc.so') lib.increment 

Izvade:

 

Iepriekš minētajā kodā ctypes.CDLL atgriež koplietotu objektu ar nosaukumu libinic.tātad. Tas satur incrPointer() funkciju. Ja mums ir jānorāda rādītājs uz funkcijām, kuras mēs definējam koplietotā objektā, mums tas ir jānorāda, izmantojot ctypes. Apskatīsim zemāk redzamo piemēru.

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

Ja mēs izsauksim funkciju, izmantojot citu veidu, tas radīs kļūdu.

 incrPointer(10) 

Izvade:

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

Tas ir tāpēc, ka incrPointer ir nepieciešams rādītājs, un ctypes ir veids, kā Python rādīt rādītāju.

 v = ctypes.c_int(10) 

v ir C mainīgais. Ctypes nodrošina metodi, ko sauc byref() kas izmantoja mainīgā atsauces nodošanu.

 inc(ctypes.byref(a)) a 

Izvade:

c_int(11) 

Mēs esam palielinājuši vērtību, izmantojot atsauces mainīgo.

Secinājums

Mēs esam apsprieduši, ka rādītāja Python nav, taču mēs varam īstenot to pašu uzvedību ar *mutable objektu. Mēs arī apspriedām ctypes moduļus, kas var definēt C rādītāju Python. Mēs esam definējuši dažus lieliskus veidus, kā simulēt rādītāju Python.