Idea
Nyt tullaan ehkä hyödyllisempään asiaan ohjelmoinnin opiskelussa, funktioihin.
Funktiot ovat kaikkien ohjelmointikielien ja kaikkien ohjelmien uudelleen ja
taas uudelleen käytettäviä rakennuspalikoita.
Ilman niitä ohjelmoinnista ei tule oikeastaan yhtään mitään.
Niiden kanssa koodaukseen tulee mielekkyyttä ja tehokkuutta.
Siispä paneudu seuraavaan tekstiin ja mallikoodeihin huolella ja niin,
että varmasti ymmärrät funktioihin liittyvät termit, käsitteet, siis miten homma toimii.
Siten Sinulle avautuvat ovet oikeaan ohjelmointiin.
Ja tässä tulee samalla myös perustieto jota tarvitaan kaikessa ohjelmoinnissa
kun ryhdyt opiskelemaan ja käyttämään muita ohjelmointikieliä.
Sillä ammattilaiseksi tai kovan tason harrastajaksi Sinulla on pyrkimys.
Eik vaa?
Ties mihin vielä päädyt.
Yleistä
Kun perusopit ovat hanskassa aloitetaan ”oikeiden töiden” teko.
Silloin työstetään ohjelmia, jotka sisältävät satoja, tuhansia ja jopa kymmeniä tuhansia koodirivejä.
Helsinkiläinen opiskelija Linus Torvalds aloitti Linux-käyttöjärjestelmän koodaamisen 1991 tyhjästä ja
nyt hänen johtaa projektia jossa on yli 20 miljoonaa koodiriviä.
Ja lisää tulee.
Jos tällainen ohjelma koostuisi vain yhdestä osasta jossa suoritettavat ohjelmarivit ovat peräkkäin,
sen toiminnan hahmottaminen olisi ylivoimainen tehtävä.
Yleensä ohjelmalla pyritään ratkaisemaan jokin ’ongelma’.
Ongelman ratkaisu on helpompaa jos se palastellaan osiin ja ratkaistaan pala kerrallaan.
Ohjelmoinnissa noita paloja sanotaan funktioiksi.
Pienen tai isommankin funktion koodaaminen ja sen muuttaminen (ja varsinkin vikojen etsiminen)
helpottuu, kun toimenpiteen voi keskittää yhteen olioon koko koodin sijasta.
Yksittäinen ohjelma koostuu pääasiassa funktioista.
Funktio on itsenäinen pieni koodin pätkä, joka tekee jonkin (mielellään) yksittäisen tehtävän.
Funktiot ovat oikeastaan aliohjelmia.
Niitä käyttämällä ohjelmista tulee helpommin hallittavia.
Tärkeä etu varsinkin sulautetuissa järjestelmissä (IoT) on se, että ne vähentävät tarvittavan muistin määrää.
Samaa funktiota voidaan kutsua yhä uudelleen ja uudelleen.
Hyvin tärkeä seikka on myös uudelleen käytettävyys.
Kerran kunnolla tehty, perusteellisesti testattu ja hyväksi havaittu funktio on yleiskäyttöinen.
Sitä voidaan hyödyntää muissakin ohjelmissa. Säästyy aikaa ja vaivaa.
Sen lisäksi, että ohjelman jakaminen funktioihin selkeyttää ohjelmaa, niin se myös säästää työtä.
Jos jokin ohjelman osa pitää suorittaa monta kertaa,
riittää kun kirjoittaa tähän osaan kuuluvat käskyt yhden kerran yhdeksi funktioksi.
Tämän jälkeen riittää kun kirjoittaa tuon funktion kutsun, aina kun kyseinen osa halutaan suorittaa.
Funktioita on kahta sorttia:
- toisten tekemiä, järjestelmän sisällä olevia ja
- omatekemiä, ‘user-defined functions’.
Kummatkin sisältävät koodia jonkin tehtävän hoitamiseen.
Toisin laskien funktioita on kolmea sorttia:
- funktioita, jotka ovat aina käytettävissä
(ovat osa järjestelmää, tuttuja mm print(), len(), input(), range())
- funktioita, jotka saadaan käyttöön importoimalla ulkoisia moduuleita (esim time)
- ja omatekemiä (joita kohta tehdään)
Funktion käyttöön liittyvät peruskäsitteet:
** funktion määrittely, rakenne, function declaration
** funktion kutsu, function call
** funktioiden välinen tiedonsiirto parametrien ja paluuarvojen avulla
** paikalliset ja globaalit muuttujat
Missä kohtaa koodia ja miten omatekemät funktiot määritellään?
Python-tulkin tulee tietää etukäteen funktion olemassaolosta, siis ennen kuin sitä voidaan käyttää.
Siksi omatekemät funktiot pitää määritellä ennen pääohjelmaa (main), tai niitä vastaavia käskyrivejä.
Omatekemät funktiot
Funktion määritys on itse funktio.
Funktio määritellään komennolla def, definition,
jonka jälkeen tulee funktion nimi, eli nimi jolla funktiota kutsutaan.
Funktion nimen jälkeen tulee kaarisulut ja kaksoispiste.
Kaksoispisteen jälkeen alkaa lohko, jossa määritetään mitä funktio tekee, siis sen toiminnallisuus käskyrivien muodossa.
Lohkossa voi olla iso määrä normaaleita koodirivejä ja uusia funktiokutsuja.
Lohko sisennetään tabuloimalla tai automaatisesti kuten Thonny tekee.
Siis näin:
def funki():
käskyrivit
Funktion loppuminen kerrotaan sisennyksen päättymisellä.
Funktio koodataan tekemään mieluusti vain yhden tehtävän. Silloin sen toiminta on helppo hahmottaa.
Koodirivejä tulee muutamasta rivistä muutamaan kymmeneen.
Funktion nimen tulisi olla sen toimintaa kuvaava, esim tulosta(), lue_anturi(), start_motor()...
Funktion kutsu
Vaikka funktio on määritelty oikeaoppisesti, niin sitä ei suoriteta ennen kuin jokin toinen funktio kutsuu sitä.
Funktiota kutsutaan nimellä, esim. funki().
Kun funktiota kutsutaan, ohjelman suoritus siirtyy kutsuttavaan funktioon ja kun se päättyy,
palataan kutsuvaan funktioon kutsukäskyä seuraavaan käskyyn.
Kutsu koostuu nimestä eli tunnuksesta ja jos käytössä on parametri/argumentti tai useampi,
niin nimen perässä välittömästi suluissa olevasta argumenttilistasta.
Funktion kutsu voi olla joko pääohjelmassa tai sitten toisen funktion sisällä.
Funktio on ohjelmamuistissa vain yhdessä paikassa, mutta sitä voidaan käyttää (kutsua) kuinka monta kertaa tahansa ja
mistä kohtaa ohjelmaa tahansa.
Kutsutyypit:
funki()
- jos kutsuttava funktio ei palauta arvoa, eikä kutsuja välitä argumentteja
funki(para)
- jos kutsuva funktio siirtää dataa kutsuttavalle, se tapahtuu funktion kutsussa parametrien välityksellä.
Niistä oma esimerkki edempänä.
rele = funki()
- jos kutsuttava funktio palauttaa arvon, niin se tapahtuu return-lauseella ja palautusarvo
tulee (tässä esimerkissä) rele-muuttujan arvoksi
Mitä teknisesti tapahtuu funktiota kutsuttaessa?
Kun ohjelmassa suoritetaan funktion kutsu,
niin ensiksi laitetaan paluuosoite pinomuistiin (RAM-muistin osa).
Sitten kutsussa olevien parametrien arvot kopioidaan tuohon pinoon.
Kun ohjelma ’hyppää’ kutsuttuun funktioon,
niin parametrit (argumentit) ovat siinä omina paikallisina muuttujina ja kutsuttu ohjelma voi niitä käyttää.
Kun funktion suoritus on valmis,
pinosta palautetaan kutsuneen funktion paluuosoite prosessorin ohjelmalaskurin arvoksi
ja ohjelman suoritus ’hyppää’ takaisin funktion kutsua seuraavaan käskyyn.
Samalla kaikki paikalliset muuttujat, parametrit, hävitetään pinosta.
Parametrit ovat siis paikallisia muuttujia.
Niistä kohta lisää.
Funktioihin liittyvät asiat opitaan parhaiten siten, että tutkitaan mallikoodia ja tehdään harjoituksia,
jossa käytetään noita ylläolevia peruskäsitteitä.
Jokaiseen mallikoodiin liittyy tehtävä, jossa itse teet omia muunnoksia koodiin ja tutkit mitä se vaikuttaa toimintaan.
Miten se pyörällä ajo opittiin?
Ja eikun koodaamaan.
Eka funktio malli
Pääohjelma tässä mallissa koostuu vain funktion kutsuista ja print-lauseista.
Funktiossa vain tulostetaan lause jolla kerrotaan missä ollaan.
Mallikoodi hello()
Funktio hello() määritetään ennen varsinaista pääohjelmaa.
Funktion määritys tapahtuu avainsanalla def hello():
sitten funktion nimi, kaarisulkeet ja kaksoispiste.
Funktion runko joka sisältää käskyt, sisennetään tabuloimalla, tässä vain yksi käskyrivi.
Kaarisulkuja tarvitaan kun funktion kutsussa siirrämme dataa kutsuttuun funktioon.
Malta vielä tovi, niiden aika tulee hyvinkin pian.
Huomaa funktion rungon, lohkon, sisennys, muuten se ei toimi. Kokeile poistaa sisennys.
Seuraa rivi riviltä mitä ohjelmassa tapahtuu, niin se on siinä. Helppoa kuin heinän teko.
Toka malli jossa main-funktio
Määritetään kaksi eri funktiota, main() ja hello().
Tämä mallikoodi alkaa main-funktion kutsusta, josta kutsutaan hello-funktiota.
Ohjelman eteneminen selviää kun seuraat ohjelman tulostuksia ja vertaat niitä koodiin.
Kommentoi main-funktion kutsu pois toiminnasta, talleta ja aja.
Miten toimii? Palauta malli entiselleen.
Main()-funktio
Tähän mennessä emme ole käyttäneet main-funktiota ja hyvinhän tekemämme koodit ovat toimineet.
Tämä siksi, että poikkeuksena muista kielistä kuten java ja C-kieli, Pythonissa ei tarvita main-funktiota.
Se ei ole pakollinen.
Pelkät käskyrivit sen tilalla riittävät.
Koska tulkin täytyy olla tietoinen mitä funktioita on käytössä,
niiden määritys tehdään aina ennen noita pääohjelman käskyrivejä tai main-funktiota.
Tässä vaiheessa kurssia käytämme main-funktiota vain malliksi, sillä sen käyttö on hyvä ymmärtää ja
osata kun ryhdymme opiskelemaan muita kieliä.
Se tuo ryhtiä ohjelmiimme ja käytettävistä muuttujista ei tule ongelmaa.
Main-funktion käytöstä myöhemmin enemmän lisää kun perehdymme moduulien käyttöön.
Funktio kutsuu toista funktiota
Pääohjelma tai main-funktio ei suinkaan ole ainoa joka voi kutsua funktioita.
Funktiot voivat kutsua myös toisiaan.
Koodin seuraaminen ja vertaaminen tulostuksiin selvittää miten koodi toimii.
Kun parin oppitunnin jälkeen siirrytään opiskelemaan laiteläheistä koodia,
niissä käytetään paljon funktioita,
silloin funktion merkitys parametreineen ja ennenkaikkea sen käytön helppous selviää lopullisesti.
Miten se menikään; tieto on kumuloituvaa.