Arvutiteaduse instituut
  1. Kursused
  2. 2022/23 kevad
  3. Programmeerimise alused (MTAT.03.236)
EN
Logi sisse

Programmeerimise alused 2022/23 kevad

  • Pealeht
  • 1. Sissejuhatus
  • 2. Tingimuslause
  • 3. Tsükkel
  • 4. Järjend
  • 5. Funktsioon
  • 6. Andmevahetus. Lihtne kasutajaliides
  • Loengud
  • Moodle
  • Lahendus
  • Thonny paigaldamine
  • Thonny logide esitamine
  • Silumine
  • Kiireksamist
  • Viited
< eelmine5. nädala sisukordjärgmine >

5.3 Argumendid, muutujad

MITU FUNKTSIOONI KOOS

Vaatame näiteid, 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

ARGUMENTIDEST VEEL

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

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

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

Eks me saime ju nö otse failistki for-tsükli abil ridahaaval toimetada. Nüüd aga saame järjendi elemendile (mis vastab faili reale) ka indeksi abil juurde. Samuti oleme reavahetuse ka rea lõpust eemaldanud.

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

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

See funktsioon tagastas järjendi. See on üheks võimalikuks viisiks mitme väärtuse tagastamiseks. Nimelt saab tegelikult alati tagastada vaid ühe väärtuse. Kui on mitut vaja tagastada, tuleb kasutada sobivat andmestruktuuri, mis siis ühena teisi hõlmab.

Mõnikord on konkreetse argumendi väärtus peaaegu alati sama ja oleks tüütu seda alati 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.

def kas_kiiruse_ületamine(kiirus, piirkiirus = 90):
    return kiirus > piirkiirus

print(kas_kiiruse_ületamine(100))
print(kas_kiiruse_ületamine(90, 70))

Vaikeväärtus on ka funktsiooni print argumendil end. Nimelt vaikimisi vahetab print rida, argument end = "\n". Võime aga ka ise selle argumendi väärtuse ette anda.

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

Sõnedega oleme kasutanud ka funktsioone, mis on sõnega ühendatud punktiga.

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

Tundub nagu oleks sellisel juhul 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. Meie siin kursusel kasutame meetodeid küll (just eriti sõnede puhul), aga põhjalikum käsitlus jääb selle kursuse raamest välja.

LOKAALSED JA GLOBAALSED MUUTUJAD

Olgu meil programm, milles on defineeritud funktsioon ja siis seda rakendatud.

def summa_funktsioon(a, b, c):
    summa = a + b + c
    return summa

print(summa_funktsioon(1, 2, 3))

Pannes programmi tööle saame ekraanile arvu 6, mis muidugi ongi 1 + 2 + 3 korral oodatud.

Lisame programmile rea print(summa).

def summa_funktsioon(a, b, c):
    summa = a + b + c
    return summa

print(summa_funktsioon(1, 2, 3))
print(summa)

Saame veateate, mis väidab, et NameError: name 'summa' is not defined. Nimi summa ei ole defineeritud (kirjeldatud). Kuna funktsiooni sees toimuv on funktsiooni "siseasi", siis tõepoolest muutujat summa pole väljaspool funktsiooni olemas. Sellist funktsiooni kehas (kirjelduses) defineeritud muutujat nimetatakse lokaalseks muutujaks. Kui tõstame printimise funktsiooni kirjelduse sisse, siis on kõik korras.

def summa_funktsioon(a, b, c):
    summa = a + b + c
    print(summa)
    return summa

print(summa_funktsioon(1, 2, 3))

Esimene 6 tuleb ekraanile print(summa) toimel ja teine 6 print(summa_funktsioon(1, 2, 3)) toimel.

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

def summa_funktsioon(a, b, c):
    summa = a + b + c
    print(b)
    return summa

print(summa_funktsioon(1, 2, 3))

Funktsioonist väljas aga mitte.

def summa_funktsioon(a, b, c):
    summa = a + b + c
    return summa

print(summa_funktsioon(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 programmi põhiosas kasutuses (või mõnes teises funktsioonis kasutuses olnud).

VIDEO, MIS NÄITAB THONNYS VÄÄRTUSI

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

def summa_funktsioon(a, b, c):
    summa = a + b + c
    return summa

summa = 10
print(summa_funktsioon(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 globaalset muutujat seal kasutada ei saa. Eelmises näites just nii oligi.

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

def summa_funktsioon(a, b, c):
    summa = a + b + c + gm
    return summa

gm = 17 # globaalne muutuja
print(summa_funktsioon(1, 2, 3))

Kui me ei tea, mitu arvu on vaja kokku liita, võime kasutada summeerimiseks globaalset muutujat.

def summa_akumulaator(a):
    global summa
    summa += a
    return summa

summa = 0
summa_akumulaator(1)
summa_akumulaator(2)
summa_akumulaator(3)
print(summa)

Võtmesõna global on funktsioonis summa_akumulaator vajalik, sest muutujad, millele funktsiooni sees omistatakse väärtus, on vaikimisi lokaalsed.

Teatud juhtudel on globaalsete muutujate kasutamine funktsioonis ebasoovitav ja nii võib näiteks ka kontrollülesannete automaatkontrolli tagasiside sellele tähelepanu juhtida.

Nagu näeme, sedapidi kasutamine toimib. Programmi põhiosas defineeritud muutujaid nimetatakse globaalseteks muutujateks. Nendele pääsetakse ligi nii programmi põhiosas, kui funktsioonide sees.

Mõnevõrra meelevaldselt võib võrdluseks tuua lokaalse ja globaalse tuntuse inimeste hulgas. Näiteks Eestis tuntud inimene, keda siin igal sammul ära tuntakse, võib väljaspool Eestit rahulikult tundmatuna liikuda. Vastupidi aga globaalne staar on tuntud ka Eestis.

ENESEKONTROLL

x = 1

def f():

    y = 2
    print(x)
    print(y)

f() print(x) print(y)

Just sai öeldud, et lokaalsetele muutujatele võib nimesid valida ilma teiste funktsioonide või programmi põhiosa pärast muretsemata. Mis aga juhtub, kui lokaalse muutuja nimi ühtib mõne globaalse muutuja nimega?

x = 1

def f():
    x = 2
    print(x)

print(x) # ekraanile kuvatakse 1
f()      # ekraanile kuvatakse 2
print(x) # ekraanile kuvatakse 1

Funktsiooni sees defineeritud muutuja x ei mõjuta kuidagi samanimelist globaalset muutujat, tegemist on kahe erineva muutujaga, millel on juhtumisi sama nimi. Sellisel juhul me ei saa funktsiooni f sees enam ligi globaalsele muutujale x.

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, kuid ei tagasta midagi, ja teised arvutavad midagi ning tagastavad tulemuse.

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.


< eelmine5. nädala sisukordjärgmine >
  • Arvutiteaduse instituut
  • Loodus- ja täppisteaduste valdkond
  • Tartu Ülikool
Tehniliste probleemide või küsimuste korral kirjuta:

Kursuse sisu ja korralduslike küsimustega pöörduge kursuse korraldajate poole.
Õppematerjalide varalised autoriõigused kuuluvad Tartu Ülikoolile. Õppematerjalide kasutamine on lubatud autoriõiguse seaduses ettenähtud teose vaba kasutamise eesmärkidel ja tingimustel. Õppematerjalide kasutamisel on kasutaja kohustatud viitama õppematerjalide autorile.
Õppematerjalide kasutamine muudel eesmärkidel on lubatud ainult Tartu Ülikooli eelneval kirjalikul nõusolekul.
Courses’i keskkonna kasutustingimused