Šioje pamokoje sužinosime apie žymeklį „Python“ ir pamatysime, kodėl „Python“ nepalaiko rodyklės sąvokų.
Taip pat suprasime, kaip galime imituoti žymeklį Python. Žemiau pateikiamas rodyklės įvadas tiems, kurie apie tai nieko neturi.
Taip pat suprasime, kaip galime imituoti žymeklį Python. Žemiau pateikiamas rodyklės įvadas tiems, kurie apie tai nieko neturi.
Kas yra Rodyklė?
Rodyklė yra labai populiarus ir naudingas įrankis kintamojo adresui saugoti. Jei kas nors kada nors dirbo su žemo lygio kalba, pvz C . C++ , jis tikriausiai būtų susipažinęs su rodyklėmis. Jis labai efektyviai valdo kodą. Pradedantiesiems tai gali būti šiek tiek sudėtinga, tačiau tai yra viena iš svarbiausių programos koncepcijų. Tačiau tai gali sukelti įvairių atminties valdymo klaidų. Taigi, rodyklių apibrėžimas -
„Rodyklės yra kintamieji, kuriuose yra kito kintamojo atminties adresas. Rodyklės kintamieji pažymėti žvaigždute (*).'
Pažiūrėkime šį žymeklio pavyzdį C programavimo kalba.
Pavyzdys – kaip naudoti žymeklį 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; }
Išvestis:
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
Be to, kad rodyklės yra naudingos, jos nenaudojamos Python . Šioje temoje aptarsime Python objektų modelį ir sužinosime, kodėl Python neegzistuoja rodyklės. Taip pat išmoksime įvairių būdų, kaip imituoti rodykles Python. Pirmiausia aptarkime, kodėl Python nepalaiko rodyklių.
Kodėl Python nepalaiko rodyklių
Tiksli priežastis, kodėl nepalaikoma rodyklė, nėra aiški. Ar „Python“ žymeklis gali egzistuoti vietoje? Pagrindinė Python koncepcija yra jos paprastumas, tačiau rodyklė pažeidė Python Zen. Rodyklės dažniausiai skatinamos daryti numanomus, o ne aiškius pakeitimus. Jie taip pat yra sudėtingi, ypač pradedantiesiems.
Rodikliai linkę sukurti kodo sudėtingumą, kai Python daugiausia dėmesio skiria patogumui, o ne greičiui. Dėl to Python nepalaiko rodyklės. Tačiau Python suteikia tam tikrų pranašumų naudojant žymeklį.
Prieš suprasdami žymeklį Python, turime turėti pagrindinę idėją apie šiuos dalykus.
- Nekintami vs kintami objektai
- Python kintamieji/pavadinimai
Objektai Python
Python programoje viskas yra objektas, net klasė, funkcijos, kintamieji ir tt Kiekviename objekte yra bent trys duomenų dalys.
masyvo rūšiavimo java
- Nuorodų skaičius
- Tipas
- Vertė
Aptarkime po vieną.
Nuorodų skaičius – Jis naudojamas atminties valdymui. Norėdami gauti daugiau informacijos apie Python atminties valdymą, skaitykite Atminties valdymas Python.
Tipas - The CPython sluoksnis naudojamas kaip tipas, siekiant užtikrinti tipo saugumą vykdymo metu. Galiausiai yra vertė, kuri yra tikroji vertė, susieta su objektu.
Jei įsigilinsime į šį objektą, pamatysime, kad ne visi objektai yra vienodi. Svarbus skirtumas tarp objektų tipų yra nekintantis ir kintantis. Visų pirma, turime suprasti skirtumą tarp objektų tipų, nes jis tyrinėja žymeklį Python.
Nekintami vs kintami objektai
Nekeičiami objektai negali būti modifikuojami, o kintamieji objektai gali būti modifikuoti. Pažiūrėkime toliau pateiktą įprastų tipų lentelę ir tai, ar jie yra keičiami, ar ne.
Objektai | Tipas |
---|---|
Tarpt | Nekintama |
Plūdė | Nekintama |
Bool | Nekintama |
Sąrašas | Keičiamas |
Nustatyti | Keičiamas |
Sudėtingas | Keičiamas |
Tuple | Nekintama |
Frozenset | Nekintama |
Dikt | Keičiamas |
Aukščiau nurodytų objektų tipą galime patikrinti naudodami id () metodas. Šis metodas grąžina objekto atminties adresą.
Toliau pateiktas eilutes rašome REPL aplinkoje.
x = 5 id(x)
Išvestis:
140720979625920
Aukščiau pateiktame kode x reikšmę priskyrėme 10. jei pakeistume šią reikšmę su pakeitimu, gautume naujus objektus.
x-=1 id(x)
Išvestis:
140720979625888
Kaip matome, modifikuojame aukščiau pateiktą kodą ir kaip atsaką gauname naujus objektus. Paimkime dar vieną pavyzdį g .
s = 'java' print(id(s)) s += 'Tpoint' print(s) id(s)
Išvestis:
konvertuoti eilutę į int
2315970974512 JavaTpoint 1977728175088
Vėlgi, mes modifikuojame x reikšmę pridėdami naują eilutę ir gauname naują atminties adresą. Pabandykime pridėti eilutę tiesiai į s.
s = 'java' s[0] = T print(id(s))
Išvestis:
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
Aukščiau pateiktas kodas grąžina klaidą, tai reiškia, kad eilutė nepalaiko mutacijos. Taigi g yra nekintantys objektai.
Dabar pamatysime kintamą objektą, pvz., sąrašą.
my_list = [3, 4, 8] print(id(my_list)) my_list.append(4) print(my_list) print(id(my_list))
Išvestis:
2571132658944 [3, 4, 8, 4] 2571132658944
Kaip matome aukščiau pateiktame kode, mano_sąrašas iš pradžių turi ID, o prie sąrašo pridėjome 5; mano_sąrašas turi tą patį ID, nes sąrašas palaiko kintamumas.
Python kintamųjų supratimas
Python kintamųjų apibrėžimo būdas gerokai skiriasi nuo C arba C++. Python kintamasis neapibrėžia duomenų tipo. Tiesą sakant, Python turi pavadinimus, o ne kintamuosius.
Taigi turime suprasti skirtumą tarp kintamųjų ir pavadinimų, ir tai ypač aktualu, kai naršome sudėtingą rodyklių temą Python.
Supraskime, kaip kintamasis veikia C ir kaip pavadinimas veikia Python.
Kintamieji C
C kalboje kintamasis yra tas, kad jis turi vertę arba saugos vertę. Jis apibrėžiamas pagal duomenų tipą. Pažiūrėkime šį kodą, kuris apibrėžia kintamąjį.
int x = 286;
- Paskirkite pakankamai atminties sveikajam skaičiui.
- Tai atminties vietai priskiriame reikšmę 286.
- X reiškia tą reikšmę.
Jei atstovaujame atminties požiūriui -
Kaip matome, x turi atminties vietą reikšmei 286. Dabar naują reikšmę priskirsime x.
x = 250
Ši nauja reikšmė perrašo ankstesnę vertę. Tai reiškia, kad kintamasis x yra kintamas.
X reikšmės vieta yra ta pati, bet reikšmė pasikeitė. Tai yra reikšmingas taškas, rodantis, kad x yra atminties vieta, o ne tik jos pavadinimas.
Dabar pristatome naują kintamąjį, kuris užima x, tada y sukuria naują atminties dėžutę.
aibių algebra
int y = x;
Kintamasis y sukuria naują langelį, pavadintą y, nukopijuoja x reikšmę į langelį.
Vardai Python
Kaip aptarėme anksčiau, Python neturi kintamųjų. Jis turi pavadinimus, ir mes naudojame šį terminą kaip kintamuosius. Tačiau yra skirtumas tarp kintamųjų ir pavadinimų. Pažiūrėkime toliau pateiktą pavyzdį.
x = 289
Aukščiau pateiktas kodas suskaidomas vykdymo metu.
- Sukurkite PyObject
- Nustatykite PyObject tipo kodą į sveikąjį skaičių
- Nustatykite PyObject reikšmę į 289
- Sukurkite pavadinimą x
- Nukreipkite x į naują PyObject
- Padidinkite PyObject perskaičiavimą 1
Tai atrodys taip, kaip nurodyta žemiau.
Mes galime suprasti vidinį kintamojo veikimą Python. Kintamasis x nurodo objekto nuorodą ir jame nėra atminties vietos, kaip anksčiau. Taip pat rodoma, kad x = 289 susieja pavadinimą x su nuoroda.
Dabar pristatome naują kintamąjį ir jam priskiriame x.
y = x
Python kintamasis y nesukurs naujo objekto; tai tik naujas pavadinimas, nurodantis į tą patį objektą. Objektas perskaičiavimas taip pat padidėjo vienu. Galime tai patvirtinti taip.
y is x
Išvestis:
True
Jei padidinsime y reikšmę vienu, tai nebebus nuoroda į tą patį objektą.
y + =1 y is x
Tai reiškia, kad Python sistemoje kintamųjų nepriskiriame. Vietoj to, mes susiejame pavadinimus su nuoroda.
Rodyklės modeliavimas Python
Kaip jau aptarėme, „Python“ nepalaiko rodyklės, tačiau galime pasinaudoti rodyklės naudojimu. Python siūlo alternatyvius būdus, kaip naudoti žymeklį Python. Šie du būdai pateikti žemiau.
- Keičiamų tipų naudojimas kaip rodyklės
- Naudojant pasirinktinius Python objektus
Supraskime pateiktus taškus.
Keičiamų tipų naudojimas kaip žymeklis
Ankstesniame skyriuje apibrėžėme kintamo tipo objektus; galime elgtis su jais taip, lyg tai būtų rodyklės, imituojančios rodyklės elgesį. Supraskime šį pavyzdį.
C
void add_one(int *a) { *a += 1; }
Aukščiau pateiktame kode apibrėžėme žymeklį *a, tada padidiname reikšmę vienu. Dabar mes jį įgyvendinsime naudodami main() funkciją.
kiek miestų yra JAV
#include int main(void) { int y = 233; printf('y = %d ', y); add_one(&y); printf('y = %d ', y); return 0; }
Išvestis:
y = 233 y = 234
Šio tipo elgesį galime imituoti naudodami Python kintamąjį tipą. Supraskite šį pavyzdį.
def add_one(x): x[0] += 1 y = [2337] add_one(y) y[0]
Aukščiau pateikta funkcija pasiekia pirmąjį sąrašo elementą ir padidina jo reikšmę vienu. Kai vykdome aukščiau pateiktą programą, ji išspausdina pakeistą y reikšmę. Tai reiškia, kad galime pakartoti žymeklį naudodami kintamą objektą. Bet jei bandysime imituoti žymeklį naudodami nekintamą objektą.
z = (2337,) add_one(z)
Išvestis:
Traceback (most recent call last): File '', line 1, in File '', line 2, in add_one TypeError: 'tuple' object does not support item assignment
Aukščiau pateiktame kode naudojome eilutę, nekintamą objektą, todėl jis grąžino klaidą. Taip pat galime naudoti žodyną, norėdami imituoti žymeklį Python.
Supraskime šį pavyzdį, kuriame skaičiuosime kiekvieną programoje atliekamą operaciją. Tam galime pasitelkti diktą.
Pavyzdys -
count = {'funcCalls': 0} def car(): count['funcCalls'] += 1 def foo(): count['funCcalls'] += 1 car() foo() count['funcCalls']
Išvestis:
2
Paaiškinimas -
Aukščiau pateiktame pavyzdyje mes panaudojome skaičiuoti žodynas, kuriame buvo sekamas funkcijų iškvietimų skaičius. Kai foo () funkcija iškviečiama, skaitiklis padidinamas 2, nes dict yra keičiamas.
Python objektų naudojimas
Ankstesniame pavyzdyje naudojome dict, kad mėgdžiotume žymeklį Python, tačiau kartais tampa sunku prisiminti visus naudojamus raktų pavadinimus. Vietoj žodyno galime naudoti pasirinktinę Python klasę. Supraskime šį pavyzdį.
Pavyzdys -
class Pointer(object): def __init__(self): self._metrics = { 'funCalls': 0, 'catPictures': 0, }
Aukščiau pateiktame kode apibrėžėme Pointer klasę. Ši klasė naudojo diktą faktiniams duomenims laikyti kintamajame _metrics. Tai suteiks mūsų programai kintamumo. Tai galime padaryti taip.
class Pointer(object): # ... @property def funCalls(self): return self._metrics['func_calls'] @property def catPictures_served(self): return self._metrics['cat_pictures_served']
Mes panaudojome @nuosavybė dekoratorius. Jei nesate susipažinę su dekoratoriais, apsilankykite mūsų Python dekoratorių mokymo programoje. @Property dekoratorius pasieks funCalls ir catPicture_served. Dabar sukursime Pointer klasės objektą.
pt = Pointer() pt.funCalls() pt.catPicture_served
Čia turime padidinti šias vertes.
class Pointer(object): # ... def increament(self): self._metrices['funCalls'] += 1 def cat_pics(self): self._metrices['catPictures_served'] += 1
Apibrėžėme du naujus metodus – increment() ir cat_pics(). Mes pakeitėme reikšmes naudodami šias matricų dikto funkcijas. Čia mes galime pakeisti klasę taip pat, kaip keičiame žymeklį.
pt = Pointer() pt.increment() pt.increment() pt.funCalls()
Python ctypes modulis
Python ctypes modulis leidžia mums sukurti C tipo žymeklį Python. Šis modulis yra naudingas, jei norime iškviesti funkciją į C biblioteką, kuriai reikalingas žymeklis. Supraskime šį pavyzdį.
Pavyzdys – C kalba
void incr_one(int *x) { *x += 1; }
Aukščiau pateiktoje funkcijoje mes padidinome x reikšmę vienu. Tarkime, kad išsaugome aukščiau pateiktą failą pavadinimu incrPointer.c ir įveskite šią komandą terminale.
$ gcc -c -Wall -Werror -fpic incrPointer.c $ gcc -shared -o libinc.so incrPointer.o
Sukompiliuojama pirmoji komanda incrPointer.c į objektą, vadinamą incrPointer.o. Antroji komanda priima objekto failą ir sukuria libinic.so, kad bendradarbiautų su ctypes.
rūšiuoti masyvo sąrašą
import ctypes ## libinc.so library should be same directory as this program lib = ctypes.CDLL('./libinc.so') lib.increment
Išvestis:
Aukščiau pateiktame kode ctypes.CDLL grąžina bendrinamą objektą, vadinamą libinika.taip. Jame yra incrPointer() funkcija. Jei mums reikia nurodyti žymeklį į funkcijas, kurias apibrėžiame bendrame objekte, turime jį nurodyti naudodami ctypes. Pažiūrėkime žemiau pateiktą pavyzdį.
inc = lib.increment ## defining the argtypes inc.argtypes = [ctypes.POINTER(ctypes.c_int)]
Jei iškviesime funkciją naudodami kitokį tipą, bus padaryta klaida.
incrPointer(10)
Išvestis:
Traceback (most recent call last): File '', line 1, in ctypes.ArgumentError: argument 1: : expected LP_c_int instance instead of int
Taip yra todėl, kad incrPointer reikalauja žymeklio, o ctypes yra būdas perduoti žymeklį Python.
v = ctypes.c_int(10)
v yra C kintamasis. Ctypes pateikia metodą, vadinamą byref () kurie anksčiau perduodavo kintamojo nuorodą.
inc(ctypes.byref(a)) a
Išvestis:
c_int(11)
Mes padidinome vertę naudodami atskaitos kintamąjį.
Išvada
Aptarėme, kad rodyklės nėra Python, bet tą patį elgesį galime įgyvendinti su *kintamu objektu. Taip pat aptarėme ctypes modulius, kurie gali apibrėžti C žymeklį Python. Apibrėžėme keletą puikių būdų, kaip imituoti žymeklį „Python“.