Programos yra skaidomos į dalis, kad būtų lengviau tvarkomos, pvz, į keils failus, arba faile kodas būna suskaidytas į funkcijas. Skirtingose programos dalyse gali pasitaikyti vienodai pavadintų kintamųjų (kaip kad skirtingose šeimose būna vaikų tais pačiais vardais) - jie tarpusavy nesimaišo, nes naudojami tik tos dalies viduje - lokaliai. O kai kurie kintamieji gali būti žinomi visoje programoje - globaliai (kaip kokie visuomenės veikėjai ar pop. žvaigždės).
Kintamųjų galiojimo sritis
def square(x): value = x * x return valueŠi funkcija skaičiuoja skaičiaus
x
kvadratą. Tarkime, kad funkciją square
iškviesime iš programos, kurioje taip pat yra value
kintamasis, tačiau naudojamas kitais tikslais.
# pagrindinė programa value = 17 penki_kvadratu = square(5) print(penki_kvadratu, value)Kaip manote, kas bus atspausdinta? Nežinodami kaip Pitonas elgsis, galime svarstyti dvi galimybes:
- Arba Pitone yra du atskiri
value
kintamieji (vienas funkcijoje "square", kitas - už jos ribų ). Taigi,square
grąžins 25, betvalue
reikšmė pagrindinėje programoje išliks 17. Bus atspausdinama:25
17
. - Arba visur yra tas pats kintamasis
value
. Funkcijasquare
pakeičiavalue
reikšmę, taigi programa atspausdins:25
25
.
O kaip yra iš tikro?
Matome, jog Pitonas veikia pagal pirmąjį variantą. Vykdant funkciją, Pitonas nepakeičia kintamųjų, esančių už jos ribų. Priskyrimo veiksmai pakeičia tik “lokalius" kintamuosius - esančius funkcijos viduje. Tai natūraliai apsaugo nuo netikėtų nesusipratimų (pvz., jei kelios funkcijos naudotų tą patį kintamojo vardą).
Detaliau tai galite pamatyti 6-tame žingsnyje ("Step 6 of 8"): matosi du skirtingi kintamieji value
: vienas square
funkcijoje, o kitas už funkcijos ribų - “globalioje” programos srityje.
x = "outer" def xReplace(value): x = value xReplace("inner") print(x)
x = value
veikia tiktai viduje esantį kintamajį x
. Išorėje esantis globalus kintamasis x
nebuvo pakeistas. (taigi, funkcija xReplace
yra bevertė.)Į kintamųjų galijimo sriį ("variable scope") panaši sąvoka yra "namespace" (vardų galiojimo sritis). Jos pagalba nurodoma, kad kintamasis yra iš konkrečios programos dalies -- iš kažkurio importuoto modulio. Pvz., jei importuojame paketą math
, kuriame yra kintamąsis x
, jis nepersidengia su mūsų programos kintamuoju x
, nes pasiekiamas „per tašką“ math.x
Sričių taisyklė: pirmiau žiūrim viduje, o paskui - išorėn
Kartais prireikia funkcijos viduje panaudoti globalius kintamuosius. Pvz., programos pradžioje priskiriame kintamajam reikšmę, ir norime, kad mūsų funkcijos ją žinotų - matytų.
Funkcijoje nebuvo kintamojo favouriteTopping
, tačiau klaida neįvyko. Pitonas kintamuosius peržiūri pagal tokią tvarką: visų pirma ieško lokalaus kintamojo, o po to -- globaliai galiojančio. Mūsų atveju programa rado favouriteTopping
globalioje srityje.
Aukščiau esantys pavyzdžiai su orderPizzas ir xReplace yra beveik identiški. Kodėl xReplace kintamasis x yra lokalus, o orderPizzas atveju favouriteTopping - lieka globalus? Pitone galioja taisyklė: jei funkcijoje kintamajam priskiriama reikšmė, tai jis standartiškai padaromas lokaliu (kad nebūtų konfliktų su kitom programos dalimis). Tai pati dažniausia priežastis klaidos: UnboundLocalError : daugiau apie tai [1, 2] oficialioje Pitono dokumentacijoje. |
Funkcijos argumentai yra visada laikomi naujais lokaliais kintamaisiais. Tai pailiustruoja šis neveikiantis kodas ( jis bando kintamąjam g
priskirti reikšmę 0
).
Situacija su kintamųjų galiojimo sritimi galima palyginti su gyventojų vieša ir privačia erdve: tai, kas vieša (globalu) - žinoma visiems, o kas privatu (lokalu) - nežinoma už namo sienų.
global
'ūs pakeitimai
Aukščiau aprašytas princiapas tinka 99% atvejų. Tačiau, kartais patogu globalų kintamąjį pakeisti funkcijos viduje. Tai galima padaryti naudojant raktažodį global
.
Štai aukščiau buvusio xReplace
modifikacija: nurodžius, kad kintamasis yra global
'us, jo reikšmė pakeičiama iš "outer" į "inner":
Kaip jau minėjome, norint panaudoti globalaus kintamojo reikšmę, nereikia naudoti global
. Jis naudojamas tik norint priskirti/pakeisti reikšmes.
P.s.: 13 pamokoje išmoksite apie sąrašus -- jų pertvarkymus funkcijojse galima daryti be global
, ir jie išliks, nes sąrašų saugojimas atmintyje įdomesnis negu paprastų kintamųjų ;).