Funktsiooni mõiste ja kasutamine
Põhikoolist alates on matemaatikas kasutatud erisuguseid funktsioone. Näiteks y = 2x lubab leida y väärtuse, erisuguste x väärtuste puhul. Programmeerimises on funktsioonide kasutamine samuti väga oluline, kuna nad võimaldavad:
Struktureerida programmi nii, et see oleks lugejale arusaadavam.
Olemasolevat koodi taaskasutada ja kohandada sõltuvalt kontekstist.
Vähendada programmi arenduse ning hoolduse maksumust, kuna programm on selgem ja kvaliteetsem.
Funktsioonid on universaalsed ja kasutusel peaaegu igas programmeerimiskeeles.
Vaata allolevast videost, miks ja kuidas tasuks koodis kasutada funktsioone.
Juba esimestes programmides kasutasime näiteks funktsiooni print
teksti kuvamiseks ja funktsiooni input
kasutajalt sisendi saamiseks. Funktsioonidel on tihti sulgudes antavad argumendid (teise sõnaga parameetrid), mis funktsiooni tööd mõjutavad.
Seni oleme kasutanud sisseehitatud funktsioone, mille on kirjutanud Pythoni arendajad. Mõned neist on laetud automaatselt (näiteks print
ja input
), teised vajavad esmalt neid sisaldava mooduli importimist. Kuna olemasolevatest funktsioonidest meile alati ei piisa, kasutame võimalust funktsioone ise juurde luua.
Funktsiooni defineerimine
Funktsiooni kirjeldamiseks ehk defineerimiseks kasutatakse võtmesõna def
.
def function_name(parameter: parameter type hint) -> type hint: # Statements, i.e. the function body
Funktsiooni loomisel tuleb peale võtmesõna def
kirjutada talle nimi (mille järgi me seda funktsiooni edaspidi välja kutsuda saame) ja seejärel sulud. Sulgudesse võib panna 0 või rohkem argumenti. Oluline on, et kõik funktsiooni sisus olevad read peavad olema esimese rea suhtes taandatud.
Funktsiooni sisemus käivitub iga kord, kui funktsioon välja kutsutakse.
Samuti võib funktsioonis olla, aga ei pea, võtmesõna return
. Kui return
ära jätta, siis funktsioon töötab lõpuni ja tagastab vaikimisi spetsiaalse väärtuse None.
Võtmesõna return
lõpetab otsekohe funktsiooni töö ja tagastab määratud väärtuse.
Kui pärast võtmesõna return
ei ole midagi, siis lõpetab funktsioon oma töö ning tagastab spetsiaalväärtuse None
.
Funktsiooni puhul on oluline, et defineerimine toimuks enne, kui funktsioon välja kutsutakse. Vastasel juhul ei oska Python sellise nimega funktsiooni korral kuidagi käituda ning annab veateate.
Allpool toodud koodis näed erinevaid näiteid funktsioonide kasutamise kohta.
# no pec
def func() -> None:
print("This is printed to the console")
return
# This line can never be reached
print(func())
# This is printed to the console
# None
def second_func() -> None:
num = 4
print(second_func()) # Prints None
def third_func() -> int:
return 5
print(third_func()) # Prints 5
Parameetritega funktsioonid
def fahrenheit(temp_in_celsius: int) -> float:
return (temp_in_celsius * 9 / 5) + 32
Siin on näha kuidas funktsioon nimega fahrenheit
võtab parameetrina sisse temperatuuri Celsiustes (temp_in_celsius
) tagastades sama temperatuuri, millega on teostatud vastav korrutamise ja liitmise operatisoon.
Teoreetiliselt võiks tagastuse asemel olla lihtsalt print()
, aga tagastamine võimaldab näiteks omistada tagastatud väärtus mingile muutujale (Muutuja).
# no pec
def fahrenheit(temp_in_celsius: int) -> float:
return (temp_in_celsius * 9 / 5) + 32
# Saving the return value into variable
temp_in_f = fahrenheit(22)
print(temp_in_f) # Prints 71.6, 22°C is 71.6°F
Edasi soovitaks tutvuda peatükiga Funktsioon, selle argumendid ning parameetrid, et saada aru eri tüüpi funktsioonidest ning seejärel siia tagasi tulla, et saada aru miks on funktsioonid nii kasulikud.
Tüübi vihjed (type hints)
Pythonis on võimalik mitmel pool vihjata võimalikule andmetüübile kasutades tüübi vihjet.
Vaatame lihtsat näidet ilma vihjeta:
def greeting(name):
"""Greet a person by name."""
return "Hello " + name
Nüüd lisame parameetrile name
tüübivihje str
, mis vihjab sellele, et tegemist võiks olla sõnega.
Kirjutame juurde ka tüübivihje tagastatavale väärtusele, milleks antud juhul on samuti str
.
def greeting(name: str) -> str:
"""Greet a person by name."""
return "Hello " + name
Miks on see kasulik?
Aitab IDE-l oluliselt efektiivsemalt määrata muutuja andmetüüpi ja seeläbi pakkuda sobivaid funktsioone. Siin esimese näite puhul ei oska PyCharm objekti tüüpi määrata, seega
.
lisamisel ei pakuta võimalike funktsioone. Teise näite puhul seevastu kuvatakse.
lisamisel terve hulk funktsioone, mida on võimalik sõnel kutsuda.Abiks dokumenteerimisel ja aitab vältida
TypeError
-eid.
Attention
Python on dünaamiliste andmetüüpidega keel ja tüübi vihjete lisamine ei keela programmeerijal teiste tüüpide kasutamist! Vale tüübi kasutamine piirdub vaid IDE hoiatusega.
Võimalik on ka vihjata mitmele tüübile, oma tehtud klassile ja palju muud.
Põhjalikumalt saab lugeda dokumentatsioonist (kirjeldatud PEP 484-s, PEP 526-s).
Koodi kordamise vältimine kasutades funktsioone
Funktsioonid vähendavad koodi hulka. Soovime näiteks tervitada kõiki oma sõpru ühekaupa. Esialgu kirjutame naiivselt sellise koodi:
print("Hello Anni, and welcome to the Python world")
print("Hello Mark, and welcome to the Python world")
print("Hello Bill, and welcome to the Python world")
print("Hello Romeo, and welcome to the Python world")
print("Hello Julia, and welcome to the Python world")
Sellele koodile peale vaadates võib näha, et koodi ülesanne on üks ja sama - tervitada inimest antud nimega. Programmeerimisel tasub jälgida DRY-printsiipi (Don´t Repeat Yourself) ehk sarnase koodi kordamist tuleks vältida. See koodijupp on hea näide sellest, mida tuleks vältida.
Kirjutame nüüd koodi ümber kasutades funktsiooni:
names = ('Anni', 'Mark', 'Bill', 'Romeo', 'Julia')
def greet(name: str) -> str:
return f"Hello {name}, and welcome to the Python world"
for name in names:
print(greet(name))
Tulemus:
'Hello Anni, and welcome to the Python world'
'Hello Mark, and welcome to the Python world'
'Hello Bill, and welcome to the Python world'
'Hello Romeo, and welcome to the Python world'
'Hello Julia, and welcome to the Python world'
Lõime funktsiooni, millel on parameeter name
ja vastavalt sellele muutub ka prinditava sõne sisu.
Paneme kõik nimed ühte ennikusse (Ennik (tuple)) ja loome tsükli (Tsükkel (loop)), mis kutsub välja meie loodud funktsiooni greet
iga
ennikus oleva nimega. Selle koodi haldamine on juba palju lihtsam.