Na hitro o globalnih spremenljivkah
Globalne spremenljivke
Bližamo se koncu predavanj. Nekateri prihajate v programersko puberteto in vas bo morda začenjalo razganjati, zato je čas, da se očki pogovorijo s sinčki in mamice s hčerkami o tisti nerodni temi: o globalnih spremenljivkah.
Vsaka funkcija se mora sramežljivo brigati samo za svoje reči. (To zdaj v
kontekstu onega zgoraj zveni čudno, zato bom nehal z metaforami.) Funkcija
dobi vse podatke prek argumentov in vrne rezultate z return
-om.
V teoriji. V praksi funkcije pogosto "vidijo" tudi kaj, česar niso dobile prek
argumentov. Če ne drugega, uporabljajo module, ki jih niso uvozile same. Poleg
tega "vidijo" funkcije, kot so len
in podobne. Ideala ni, ker bi
bil nepraktičen. Pač pa se zmenimo za seznam stvari, ki se jih ne počne, od manj
proti bolj prepovedanim:
-
Ni lepo, če funkcija bere vrednosti spremenljivk, definiranih izven
nje. Ni pa take katastrofe, če to počnemo, posebej, kadar bi bila
"pravilna" rešitev zelo nepraktična. Primer takšnega početja so vse
funkcije v zapiskih iz
rekurzije, saj berejo vrednosti iz slovarja
rodovnik
, ki ga niso dobile kot argument. Spremenljivkarodovnik
je že primer globalne spremenljivke, ker je definirana zunaj vseh funkcij. - Ni posebej lepo, če funkcija dobi argument zato, da bi v njem vrnila rezultat. Primer bi bila funkcija, ki dobi prazen seznam zato, da ga napolni. Lepše je, če funkcija vrne seznam. Vendar je takšno početje včasih smiselno, kadar si funkcije podajajo nek seznam (ali kaj drugega), ki ga "dopolnjujejo".
- Grdo je, če funkcija spreminja vrednosti globalnih spremenljivk. Primer tega bi bil, če bi funkcije iz zapiskov v rekurziji spreminjale slovar rodovnik - ohranile bi isti slovar, vendar bi vanj dodajale potomce.
- Še bolj grdo in skoraj nesprejemljivo je, da funkcija prireja nove vrednosti globalnim imenom. Primer tega bi bila funkcija, ki spremenljivki (točneje: imenu) rodovnik priredi nek popolnoma nov slovar. V kombinaciji z branjem in shranjevanjem vrednosti globalnih spremenljivk to kar kliče po napakah, ki jih bo nemogoče najti, predvsem v večjih programih. To se ne dela. In to bomo delali v domači prednalogi, kar je razlog, da se o vsem skupaj sploh pogovarjamo. (Zakaj bomo potem to delali? Ker ne znamo drugače in ker bomo na predavanjih spoznali, način programiranja, s katerim se temu izognemo. To bo tudi razlika med prednalogo in pravo domačo nalogo.
- Funkcija ne sme spreminjati vrednosti argumentov, če ni to točno tisto, kar se od nje pričakuje. Precej primerov tega ste videli v napačnih rešitvah domačih nalog.
Zdaj, ko veste, kaj se ne sme delati, vam lahko povem, kako se to naredi. Tule je funkcija, ki nekaj dela s svojimi lokalnimi spremenljivkami.
Če jo pokličemo, priredi imenom x
, y
in
z
dve vrednosti, vendar ta imena po klicu funkcije ne obstajajo
več.
Zdaj pa funkciji rečem, da sta imeni x
in y
mišljeni globalno.
Zdaj poglejmo tole:
Spremenljivko x
sem pred klicem funkcije postavil na 42.
Ko je funkcija priredila x
-u vrednost 1, se je prirejanje nanašalo
na globalno ime x
in ne na ime x
znotraj
funkcije - točneje, znotraj funkcije ni nobenega x
, edini x, ki
je, je zunanji x
.
Tudi, ko je funkcija prirejala imenu y
, je to zunanji
y
. Prej ga še ni bilo, zdaj pač je.
Ime z
pa je lokalno ime.