30 Funktsioonil on väärtus

Üldistamine. Argumendid

Üsna sageli on meil vaja peaaegu samasugust tegevust sooritada mitmes erinevas kohas. Kui eri kohtades on vaja sarnast, kuid teatud variatsiooniga koodi, siis on võimalik kirjeldada funktsioon argumentide (parameetrite) abil. Sel juhul antakse väljakutsumisel funktsioonile sisendiks argumendid ja konkreetne tulemus sõltub nende väärtustest.

Näiteks allaloendamise funktsiooni võime teha üldisemaks nii, et anname ette, millisest arvust tuleb hakata lugema. Hetkel muutub programm sellest isegi lühemaks: meil pole enam vaja rida i = 10, sest me lisame muutuja i funktsiooni nime järel olevatesse sulgudesse:

Näiteprogramm. Argumendiga loendur

from time import sleep
 
def loe_alla(i):
    while i > 0:
        print(i)
        i -= 1
        sleep(1)
 
loe_alla(4)

Nüüd on funktsioon palju paindlikum ja käitub erinevalt olenevalt argumendi väärtusest. Näites on funktsioon loe_alla välja kutsutud argumendi väärtusega 4. Sellega saab i esialgseks väärtuseks 4. Tsükli jätkamistingimus on täidetud ja nii tehaksegi esimene samm i väärtusega 4, mis väljastatakse ekraanile. Järgmine rida muudab i väärtuse ühe võrra väiksemaks ja nii edasi.

Proovi funktsiooni välja kutsuda erinevate argumentide väärtustega, nt loe_alla(8), loe_alla(1), loe_alla(-1).

Muudame nüüd ridade print(i) ja i -= 1 järjekorda ja järgmise küsimuse tarbeks kutsume selle funktsiooni välja argumendiga 6.

from time import sleep
 
def loe_alla(i):
    while i > 0:       
        i -= 1
        print(i)
        sleep(1)
 
loe_alla(6)

Enesekontroll (1 küsimus)

Video

Vaata ka kokkuvõtvat videot.

Väärtust tagastav funktsioon

Eelmised näited olid funktsioonidest, mis sooritasid mingisugused tegevused, näiteks teksti ekraanile kuvamise. Nüüd vaatame funktsioone, mis tagastavad väärtuse (õigemini on funktsioon ise selle väärtusega). Olemuselt on see sarnane funktsiooni mõiste matemaatilise käsitlusega. Igale argumendile vastab teatud väärtus, mida nimetatakse selle funktsiooni väärtuseks antud argumendi korral. Näiteks ruutfunktsiooni x2 korral vastab argumendile 4 funktsiooni väärtus 16, argumendile 5 vastab väärtus 25. Koosinusfunktsiooni korral vastab argumendile 0 funktsiooni väärtus 1, sest cos(0) = 1. Ruutjuure korral vastab argumendile 9 funktsiooni väärtus 3. Koosinuse ja ruutjuure jaoks on Pythonis funktsioonid olemas, vastavalt cos ja sqrt. Nende kasutamiseks tuleb need esmalt moodulist math importida (from math import cos, sqrt).

Olgu meil ülesandeks luua funktsioon, mis tagastab arvu ruudu. Defineerime selle funktsiooni:

Näiteprogramm. Arvu ruutu tagastav funktsioon

def ruutu(x):
    return x**2
print(ruutu(4))

Selliste funktsioonide korral, mis peavad tulemuse tagastama, on oluline käsk return, millega funktsioon väärtuse omandab. Programmi kolmas rida on funktsiooni kirjelduse järel ja rakendab vastloodud funktsiooni argumendiga 4. Rida käivitades saab ruutu(4) väärtuse 16 ja seda saab kasutada nagu tavalist arvväärtust, mille me print abil ekraanile väljastame. Saaksime seda ka avaldises kasutada, nt avaldise ruutu(4) - 17 väärtus oleks -1.

Funktsiooni tagastatav suurus võib olla ka muud tüüpi kui arv. Funktsiooni kehas võib olla rohkem ridu, kuid return-reaga funktsioon lõpetab oma töö.

Mitme argumendiga funktsioon

Funktsioonil võib olla argumente rohkem kui üks. Sel juhul eraldatakse need komadega. Järgmine funktsioon tagastab tõeväärtuse:

Näiteprogramm. Tõeväärtust tagastav mitme argumendiga funktsioon

def kas_raha_jätkub(kghind, kogus, raha):
    hind = kghind * kogus
    if hind <= raha:
        return True
    else:
        return False
 
if kas_raha_jätkub(2, 4.5, 10):
    print("Ostan")

Kuna selle funktsiooni väärtus on tõeväärtustüüpi, siis saab seda kasutada näiteks valikulause tingimuses. Antud juhul on kas_raha_jätkub(2, 4.5, 10) väärtuseks True.

Kui funktsioon võtab mitu argumenti, siis on oluline nende järjestus. Praegusel juhul antakse funktsiooni väljakutsumisel esimese argumendi väärtus muutujale kghind, teise väärtus muutujale kogus ja kolmanda väärtus muutujale raha. Võib mõelda nii, et kui funktsioon argumentidega 2, 4.5 ja 10 välja kutsutakse, siis enne funktsioonis olevate lausete juurde minemist tehakse järgmised omistuslaused: kghind = 2, kogus = 4.5 ja raha = 10. Tuleb märkida, et funktsiooni argumentide nimed on programmi seisukohalt suvalised, neist ei sõltu programmi jaoks mitte midagi (nagu ka muutujate nimede puhul), kuid nimed võiksid ikka olla sellised, mis annaksid programmi lugejale kasulikku infot koodi kohta.

Tegelikult on funktsioon kas_raha_jätkub võimalik defineerida kahe reaga (üks rida funktsiooni nime ja argumentide jaoks ning üks rida return-lause jaoks). Soovi korral püüa funktsiooni kirjeldus sellisena ümber kirjutada. Abiks võib olla teadmine, et return järel ei pruugi olla ilmutatult True või False, vaid näiteks avaldis a * b <= c.

Enesekontroll (1 küsimus)

Tagastamine ja väljastamine

Me oleme nendes materjalides kasutanud kahte küllaltki sarnast terminit: väljastamine ja tagastamine. Väljastamise all mõtleme põhiliselt millegi ekraanile manamist (eelkõige funktsiooni print abil). Tagastamise all aga peame silmas funktsiooni väärtuse tagastamist (käsu return abil). (Muudes materjalides võib sõnastus olla teistsugune.)

Kui me jaotasime funktsioone sellisteks, mis midagi ära teevad, ja sellisteks, mis väärtuse tagastavad, siis kuhu kuulub järgmine funktsioon?

def summa(x,y):
    print(x + y)

Arvutamine ilmselt toimub. Tulemus aga väljastatakse ekraanile ja seda ei tagastata – return puudub. Selline funktsioon kvalifitseerub millegi ära tegijate hulka. Selline liigitamine on oluline seepärast, et erinevatel liikidel on mõnevõrra erinevad rollid. Väärtust tagastavad funktsioonid leiavad kasutust seal, kus saab kasutada arve, tõeväärtusi, sõnesid – oleneb sellest, mis tüüpi väärtus tagastatakse. Näiteks ruutu(4) sobib tehniliselt igale poole, kuhu kõlbaks 16. Igale poole, kuhu sobib True, sobib tehniliselt ka kas_raha_jätkub(2, 4.5, 10). Nende väärtus ongi igal konkreetsel juhul see, mis vastavalt funktsiooni kirjeldusele ja etteantud argumentidele välja arvutatakse ja return-rea abil tagastatakse.

Neid funktsioone, milles return-lauset pole, rakendatakse harilikult iseseisvate lausetena. Neid ei saa kasutada avaldistes.

Proovime ekraanile väljastada sellise funktsiooni väärtust, kus midagi ei tagastata:

def summa(x,y):
    print(x + y)
print(summa(1,3))

Proovime selle programmi käivitada. Näeme, et ekraanile ilmub

4
None

Mis siin juhtus? Kõigepealt käivitati funktsioon summa(1,3) ja väljastati 1 + 3 ehk 4. Seejärel aga püüti ekraanile väljastada funktsiooni summa(1,3) väärtus. Kuna seal return-i sees pole, siis funktsioonil endal väärtust pole ja seda sümboliseerib sõna None (eesti keeles “mitte miski”). Kui tahame teha funktsiooni, mis annab võimaluse summa arvutada ja siis seda summat avaldistes edasi kasutada, siis peaksime kasutama return-lauset:

def summa(x,y):
    return x + y
print(summa(1,3))

Vaatame ka näidet, kus me tahame kahe arvu summa funktsiooni abil leida nende keskmise väärtuse. Katsetame nii return-lausega kui ilma:

def summaReturn(x,y):
    return x + y
print(summaReturn(1,3)/2)
def summaPrint(x,y):
    print(x + y)
print(summaPrint(1,3)/2)

Lisaks on veel võimalik, et funktsioon nii väljastab kui tagastab mingisuguseid väärtusi. Seda saab kasutada näiteks logifailide kirjutamiseks või vigade otsimiseks. Siiski tasuks liigset väljastamist vältida, sest see on võrdlemisi ressursinõudlik.

Funktsiooni argumentide kättesaadavus

Eespool väitsime, et iga funktsiooni väljakutsel toimub esmalt argumendiks antavate väärtuste omistamine funktsiooni argumentidele. Funktsiooni argumentidest võib mõelda kui tavalistest muutujatest, kuid olulise kitsendusega: funktsiooni argumente ei saa kasutada funktsiooni kirjeldusest väljaspool. Proovi järgnevat programmi:

def summa(x,y):
    tulemus = x + y
    return tulemus
print(summa(1,3))
print(x)

Programm annab veateate, sest muutujat x ei eksisteeri funktsiooni kirjeldusest väljaspool. Sama juhtub muutujatega, mis on defineeritud funktsiooni kirjelduses. Näiteks kui püüame rea print(tulemus) abil väljastada muutuja tulemus väärtust, siis seda saame teha vaid funktsiooni kirjelduses, väljaspool funktsiooni kirjeldust muutujat nimega tulemus ei eksisteeri. Lokaalsetest ja globaalsetest muutujatest tuleb põhjalikumalt juttu järgmises peatükis.

Enesekontroll (1 ülesanne)

Video

Vaatleme programmi, mis küsib isa brutopalga, ema brutopalga ning alaealiste laste arvu ja arvutab selle põhjal pere kuusissetuleku. Oletame, et iga alaealise lapse kohta makstakse toetust 20€ kuus. Esialgu võib eeldada, et mõlema vanema kuupalk on vähemalt sama suur kui maksuvaba miinimum.

Järgnevates videotes on see ülesanne lahendatud vastavalt ilma uut funktsiooni defineerimata ja uue funktsiooni defineerimisega . Videotes ei ole kasutatud keskkonda Thonny, kasutatud on keskkonda IDLE. Kuna videod on valminud juba mõni aasta tagasi, siis rahasummad ei pruugi olla tõepärased.

Litsents

Icon for the Creative Commons Attribution 4.0 International License

Programmeerimine on loodud Eno Tõnisson, Tauno Palts, Merilin Säde, Kaarel Tõnisson jt poolt Creative Commons Attribution 4.0 International License litsentsi alusel, kui pole teisiti märgitud.

Jaga seda raamatut