Materjalid koostas ja kursuse viib läbi
Tartu Ülikooli arvutiteaduse instituudi informaatika didaktika töörühm
< eelmine | 7. OSA sisukord | järgmine > |
7.2 Veel funktsioonidest. Funktsioonil on väärtus
ÜLDISTAMINE. ARGUMENDID
Üsna sageli on meil vaja peaaegu samasugust tegevust teha mitmes erinevas kohas. Kui eri kohtades on vaja sarnast, kuid teatud variatsiooniga koodi, siis on võimalik kirjeldada funktsioon natuke üldisemalt. Nimelt saab funktsiooni kirjeldada nii, et tema väljakutsumisel antakse ette argumendid ja konkreetne tegevus sõltub nende väärtustest.
Näiteks eelmise allalugemise funktsiooni võime teha üldisemaks nii, et anname ette, millisest arvust tuleb hakata lugema. Hetkel läheb programm sellest isegi lühemaks. Nimelt pole meil enam vaja rida i = 10
, vaid lisame hoopis muutuja i funktsiooni nime järel olevatesse sulgudesse.
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. See tähendab, et i saab 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.
Proovige 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)
Ülesanne
FUNKTSIOON TAGASTAB VÄÄRTUSE
Eelmised näited olid funktsioonidest, mis n-ö tegid midagi ära. Nüüd vaatame funktsioone, mis tagastavad väärtuse või õieti funktsioon ise ongi selle väärtusega. Tegelikult on see väga sarnane funktsiooni mõiste matemaatilise käsitlusega. Nimelt vastab igale argumendile teatud väärtus, mida nimetataksegi selle funktsiooni väärtuseks antud argumendi korral. Näiteks ruutfunktsiooni x2 korral vastab argumendile 4 funktsiooni väärtus 16, argumendile 5 aga 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 enne nad moodulist math importida (from math import cos, sqrt
).
Proovime aga ise kirjeldada funktsiooni, millega saab leida arvu ruudu ehk siis ruutfunktsiooni x2 väärtuse konkreetse argumendi korral.
def ruutu(x): return x**2 print(ruutu(4))
Pange see programm tööle!
Selliste funktsioonide korral, mis peavad tulemuse tagastama, on olulisel kohal käsk return
, millega funktsioon väärtuse omandabki. Programmi kolmas rida on juba funktsiooni kirjelduse järel ja rakendab vastloodud funktsiooni argumendiga 4. Nüüd on ruutu(4)
väärtus juba 16 ja seda saab kasutada nagu arvu ikka. Näiteks saime selle arvu ekraanile väljastada. Saaksime seda ka avaldises kasutada, nt avaldise ruutu(4) - 17
väärtus oleks -1.
Funktsiooni kirjeldus võib olla pikem, argumente võib olla rohkem (sel juhul eraldatakse need komadega) ja tagastatav suurus võib olla ka muud tüüpi kui arv. Järgmine funktsioon tagastab tõeväärtuse.
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õiks 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 ka 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 (1 rida funktsiooni nime ja argumentide jaoks ning 1 rida return-lause jaoks). Soovi korral püüdke funktsiooni kirjeldus nii ü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
.)
Ülesanne
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). (Mingites teistes materjalides võib sõnastus olla teistsugune.) Kui me jaotasime funktsioone sellisteks, mis midagi ära teevad ja sellisteks, mis väärtuse tagastavad, siis kuhu platseerub järgmine funktsioon?
def summa(x,y): print(x + y)
Arvutamine ilmselt toimub. Tulemus aga väljastatakse ekraanile ja seda ei tagastatata - 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 ja mis lihtsalt teevad midagi ära ise mingit väärtust saamata, rakendatakse harilikult iseseisvate lausetena. Neid ei saa kasutada avaldistes.
Proovime ülaltoodud funktsiooni summa korral püüda tema väärtuse ekraanile väljastada.
def summa(x,y): print(x + y) print(summa(1,3))
Proovige see programm tööle panna!
Ekraanile ilmub
4 None
Mis siis 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 aga seal return-i sees pole, 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
Proovige, mis nüüd ekraanile tuleb!
def summa(x,y): return x + y print(summa(1,3))
Varem 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. Proovige järgnevat programmi:
def summa(x,y): summa = x + y return summa print(summa(1,3)) print(x)
Saate veateate, sest muutujat x ei eksisteeri funktsiooni kirjeldusest väljaspool. Täpselt sama lugu on muutujatega, mis on defineeritud funktsiooni kirjelduses. Näiteks kui püüame rea print(summa)
abil väljastada muutuja summa väärtust, siis seda saame teha vaid funktsiooni kirjelduses, väljaspool funktsiooni kirjeldust muutujat nimega summa ei eksisteeri.
Ülesanne
MITU FUNKTSIOONI KOOS
Lõpetuseks toome mõned näited, kus funktsioone kasutatakse nii, et ühe väärtus on teise argumendiks.
ümardatud_sisestatud_arv = round(float(input("Sisestage arv "))) print("See arv ümardatult on " + str(ümardatud_sisestatud_arv))
Olge head ja testige seda suhteliselt kokkusurutud programmi.
Selle esimene rida teeb tegelikult palju asju. Tegevus algab “seestpoolt”.
- Funktsiooniga input küsitakse kasutaja käest arv. Funktsiooni input väärtus on sõne tüüpi.
- Funktsioon float võtab argumendiks sõne ja tema enda väärtuseks saab vastav ujukomaarv (murdarv). (Teiste sõnadega: Funktsioon tagastab vastava ujukomaarvu. Või veel kõnekeelsemalt: Funktsioon muudab sõne vastavaks ujukomaarvuks.)
- Funktsioon round võtab argumendiks ujukomaarvu ja ümardab selle täisarvuks.
Lõpuks määratakse see täisarv muutuja ümardatud_sisestatud_arv väärtuseks.
Niimoodi teise funktsiooni argumendiks saab olla ainult väärtust tagastav funktsioon. Sellisena saab muidugi kasutada ka isekirjeldatud funktsioone, nt
def summa(x,y): return x + y a = summa(summa(1, 3)*2, 4)
Kokkuvõtva ülevaate eelmisest näiteprogrammist annab järgmine video
Ülesanne
KOKKUVÕTE
Funktsioonid e. alamprogrammid võimaldavad (sageli küllalt keerulise) programmilõigu panna kirja ühekordselt, aga kasutada seda mitmes erinevas kohas.
Funktsiooni definitsiooni (kirjelduse) e def-lause kehas olevad laused jäetakse esialgu lihtsalt meelde. Neid saab hiljem käivitada, kirjutades funktsiooni nime koos sulgudega. Sellist tegevust nimetatakse funktsiooni väljakutseks e rakendamiseks.
Funktsiooni defineerimisel saab jätta mõned detailid lahtiseks. Täpne töö sõltub etteantud argumentide väärtustest.
Funktsioone võib jaotada kahte gruppi – ühed teevad midagi ära ja teised arvutavad ja tagastavad midagi.
Selleks, et funktsiooni saaks kasutada avaldises, peab ta arvutatud väärtuse tagastama. Väärtuse tagastamiseks kasutatakse võtmesõna return
.
< eelmine | 7. OSA sisukord | järgmine > |