31 Argumendid, muutujad

Mitu funktsiooni koos

Vaatame programmi, 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))

Katseta seda suhteliselt kokkusurutud programmi. Selle esimesel real sooritatakse hulk tegevusi. Tegevused algavad “seestpoolt”.

  • Funktsiooniga input küsitakse kasutaja käest arv. Funktsiooni input väärtus on sõnetüüpi.
  • Funktsioon float võtab argumendiks sõne ja tema enda väärtuseks saab vastav ujukomaarv. 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:

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

a = summa(summa(1, 3)*2, 4)

Video

Vaata ka eelmise ülesande kohta käivat kokkuvõtvat videot.

Enesekontroll (1 ülesanne)

Erinevad argumendid. Mitu tagastatavat väärtust

Eelnevates näidetes olid funktsioonide argumentideks tavaliselt arvud või sõned. Olenevalt funktsioonist võivad argumendid olla ka hoopis muud tüüpi. Nagu me eespool nägime, võib argumentide arv olla funktsioonidel erinev. Samuti ei pea ühe funktsiooni argumendid olema omavahel sama tüüpi.

Käsk return tagastab ainult ühe väärtuse. Kui on vaja tagastada mitu väärtust, tuleb esmalt moodustada sobiv andmestruktuur, mis teisi väärtusi hõlmab.

Koostame funktsiooni, mille argumendiks on fail ja tagastatakse sõnede järjend, mille elemendid on read sellest failist:

Näiteprogramm. Failist lugemise funktsioon

def failistSõnejärjendisse(fail):
    järjend = []
    for rida in fail:
        järjend += [rida.strip()]  # alternatiivselt: järjend.append(rida.strip())
                                   # strip() võtab lõpust ära reavahetuse
    fail.close()
    return järjend

failinimi = input("Sisestage failinimi ")
fail = open(failinimi, encoding="UTF-8")
sõned = failistSõnejärjendisse(fail)
print(sõned)
print(sõned[3])

Meie loodud funktsioon tagastab järjendi. See on üks viis, kuidas mitut väärtust tagastada.

Vaikeväärtus

Mõnikord on konkreetse argumendi väärtus peaaegu alati sama ja oleks tüütu seda iga kord uuesti ette anda. Sellisel juhul saame kasutada vaikeväärtust. Kui funktsiooni väljakutsel pole seda argumenti näidatud, siis saab argumendi väärtuseks vaikeväärtus:

Näiteprogramm. Vaikeväärtusega funktsioon

def kasKiiruseÜletamine(kiirus, piirkiirus = 90):
    return kiirus > piirkiirus
 
print(kasKiiruseÜletamine(100))
print(kasKiiruseÜletamine(90, 70))

Vaikeväärtus on ka funktsiooni print argumendil end, millega määratakse väljastatava sõne lõppu lisatav(ad) sümbol(id). Vaikimisi on lõpus reavahetus, sest argument on vaikimisi end = "\n". Me võime sellele argumendile anda ka teistsuguse väärtuse:

print("Väljastatav tekst ", end = "lõppu juurde")

Meetodid

Sõnede peatükis kasutasime funktsioone, mis on sõnega ühendatud punktiga:

print("tartu".capitalize())
print("Tartu".endswith("tu"))
print("Tartu".upper())
linn = "Tartu"
print(linn.lower())

Tundub, nagu sellisel juhul pole argument mitte sulgudes, vaid hoopis funktsiooni ees. Põhimõtteliselt see nii ongi. Selliseid funktsioone nimetatakse meetoditeks ja need on väga tavalised objektorienteeritud programmeerimises. Siinsetes materjalides me küll kasutame meetodeid (eriti sõnede puhul), aga põhjalikumalt neid ei käsitle.

Lokaalsed ja globaalsed muutujad

Eelmises peatükis mainisime, et funktsiooni sees loodavad muutujad ei ole kättesaadavad funktsioonist väljaspool. Loome näiteks funktsiooni:

def summaFunktsioon(a, b, c):
    summa = a + b + c
    return summa
 
print(summaFunktsioon(1, 2, 3))

Programmi tööle pannes saame ekraanile arvu 6, mis ongi 1 + 2 + 3 korral oodatud tulemus. Lisame programmile rea print(summa):

def summaFunktsioon(a, b, c):
    summa = a + b + c
    return summa
 
print(summaFunktsioon(1, 2, 3))
print(summa)

Saame veateate tekstiga NameError: name 'summa' is not defined ehk nimi summa ei ole defineeritud (kirjeldatud). Kuna funktsiooni sees toimuv on funktsiooni “siseasi”, siis tõepoolest pole muutujat summa väljaspool funktsiooni olemas. Sellist funktsiooni kehas (kirjelduses) defineeritud muutujat nimetatakse lokaalseks muutujaks. Kui sooritame printimise funktsiooni kirjelduse sees, toimib see tavapäraselt:

def summaFunktsioon(a, b, c):
    summa = a + b + c
    print(summa)
    return summa
 
print(summaFunktsioon(1, 2, 3))

Nüüd ilmub 6 ekraanile kahel korral: esmalt funktsiooni sees oleva print(summa) tõttu ja teist korda print(summaFunktsioon(1, 2, 3)) tõttu.

Samuti on lokaalsed ka funktsiooni argumendid. Muutuja b on funktsiooni sees täiesti olemas:

def summaFunktsioon(a, b, c):
    summa = a + b + c
    print(b)
    return summa
 
print(summaFunktsioon(1, 2, 3))

Funktsioonist väljas aga mitte:

def summaFunktsioon(a, b, c):
    summa = a + b + c
    return summa
 
print(summaFunktsioon(1, 2, 3))
print(b)

Lokaalsed muutujad luuakse funktsiooni igal käivitamisel uuesti ja nad hävivad, kui funktsioon töö lõpetab. Lokaalsed muutujad on funktsiooni siseasi, väljast neid näha pole. Neile saab panna sama nime, mis juba on programmi põhiosas (või mõnes teises funktsioonis) kasutuses olnud.

Näiteks on järgmises programmis nii funktsioonis kui põhiprogrammis muutuja summa:

def summaFunktsioon(a, b, c):
    summa = a + b + c
    return summa
 
summa = 10
print(summaFunktsioon(1, 2, 3))
print(summa)

Näeme, et viimases reas on muutuja summa väärtus just see, mis ta põhiprogrammis sai – funktsioonis toimuv tema väärtust ei muuda.

Põhiprogrammis defineeritud muutujad on globaalsed muutujad. Nende väärtusi saab kasutada nii põhiprogrammis kui ka funktsioonide sees. Kui aga funktsioonis on sama nimega lokaalne muutuja, siis samanimelist globaalset muutujat seal kasutada ei saa. Eelmises näites just nii oligi.

Järgmises näites saab globaalset muutujat funktsioonis kasutada, sest sellenimelist lokaalset muutujat funktsioonis pole:

def summaFunktsioon(a, b, c):
    summa = a + b + c + gm
    return summa
 
gm = 17   # globaalne muutuja
print(summaFunktsioon(1, 2, 3))

Teatud juhtudel on globaalsete muutujate kasutamine funktsioonis ebasoovitav, kuid seda me siinsetes materjalides ei vaatle.

Kokkuvõte

Funktsioonid ehk alamprogrammid võimaldavad (sageli küllalt keerulise) programmilõigu panna kirja üks kord, aga kasutada seda mitmes erinevas kohas.

Funktsiooni definitsiooni (kirjelduse) ehk 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 ehk 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.

Programmi põhiosas defineeritud muutujaid nimetatakse globaalseteks muutujateks, funktsiooni sees defineeritud muutujaid lokaalseteks muutujateks.

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