FUNKTIOT

Funktiot

Olemme jo käyttäneet monia erilaisia komentoja: sijoitusta, laskutoimituksia, vertailua, if:iä, for:ia ja whileä. Ruudulle tulostaminen on tehty "komentoa" print käyttäen. Listan pituus tunnistetaan "komennolla" len. Tuttuja ovat myös input ja int.

Huomaamme, että jälkimmäinen joukko edellä lueteltuja komentoja poikkeaa if:istä, for:ista, while:stä ym. siinä, että komennon perässä on sulut ja joskus sulkujen sisällä komennolle annettava tieto. "Sulkuihin päättyvät" eivät oikeastaan olekaan komentoja vaan funktioita.

Teknisesti ottaen funktio tarkoittaa koodinpätkää, jota voi kutsua muualta ohjelmakoodista. Koodirivi print("olen metodi!") siis tarkoittaa, että kutsutaan funktiota, joka suorittaa ruudulle tulostamisen. Funktion suorituksen jälkeen palataan siihen kohtaa missä ennen funktiokutsua oltiin menossa. Funktiolle suluissa annettua tietoa kutsutaan funktion parametriksi.

Parametrin lisäksi funktiolla voi olla paluuarvo. Esim. tuttu koodinpätkä:

syote = input("Kerro jotain: ")

sisältää kutsun funktioon input jolle annetaan parametrina merkkijono joka käyttäjälle näytetään. Funktiolla on paluuarvona käyttäjän syöttämä merkkijono. Vastaavasti paljon käyttämämme kokonaisluvun lukeminen:

luku = int(input("Anna kokonaisluku: "))

sisältää kaksi funktiokutsua. Ensin kutsutaan funktiota input, jonka paluuarvona on merkkijono. Funktion input palauttama merkkijono annetaan heti parametrina funktiolle int, joka palauttaa parametrina annetun merkkijonon kokonaislukuna.

Funktiokutsuja voi siis ketjuttaa siten, että "sisemmästä" funktiokutsusta palautunut arvo annetaan "ulommalle" funktiokutsulle parametrina.

Funktiokutsuja on oikeastaan kahdenlaisia. Osa liittyy muuttujiin siten, että muuttujan nimen jälkeen tulee piste ja sen jälkeen funktion nimi. Osa taas on erillisiä. Esimerkiksi listamuuttujilla on funktio append, jota käytetään yhdessä listamuuttujan kanssa listamuuttuja.append(3). Tämä yhdistäminen johtuu yksinkertaistaen siitä, että tiedettäisiin mihin listaan lisätään.

Opimme hiukan myöhemmin tarkemmin mistä tässä pisteen vasemmanpuoleisessa osassa on kyse.

Tähän mennessä käyttämämme metodit ovat kaikki olleet pythonin valmiita funktioita. Hetken kuluttua opimme tekemään myös omia funktioita.

Omat funktiot

Olemme tähän mennessä ohjelmoineet ohjelmamme siten, että kaikki tapahtuu yhdessä jatkumossa ja koodia luetaan ylhäältä alas.

Edellä puhuttiin jo funktioista, ja mainittiin että "funktio tarkoittaa koodinpätkää, jota voi kutsua muualta ohjelmakoodista". Pythonin valmiita funktioita on käytetty jo oikeastaan ensimmäisestä ohjelmasta lähtien.

Valmiiden funktioiden käytön lisäksi ohjelmoija voi kirjoittaa itse funktioita joita sovellus kutsuu. Oikeastaan on hyvin poikkeuksellista jos ohjelmassa ei ole yhtään itse kirjoitettua funktiota. Tästälähtien lähes jokainen ohjelma sisältääkin itsekirjoitettuja funktioita.

Kirjoitetaan tästä eteenpäin (kunnes toisin opitaan!) funktiot lähdekoodin yläosaan, ja funktioita itse käyttävä ohjelma funktioiden alapuolelle:

# ensin funktiomäärittelyt
def hei():
    print("No heipä hei!")
    return

# ja sitten ohjelma joka käyttää funktioita!
print("No hei.")
hei()

Ylläolevassa esimerkissä on luotu oma funktio nimeltä hei. Funktio määritellään komennolla def jonka jälkeen tulee funktion nimi, eli nimi jolla funktiota kutsutaan. Funktion nimen jälkeen tulee sulut ja kaksoispiste. Kaksoispisteen jälkeen alkaa lohko, jonka sisällä määritellään funktion toiminnallisuus.

Ylläolevassa esimerkissä funktio päätetään komennolla return, joka voidaan vapaasti suomentaa joko palaa tai palauta. Tutustumme arvon palauttaviin funktioihin hieman myöhemmin.

Kun ylläoleva esimerkki ajetaan, tulostuu seuraavanlainen teksti:

No hei.
No heipä hei!

Lähdekoodin suoritus siis alkaa funktiomäärittelyiden jälkeen. Ensin tulee vastaan komento print("No hei."), joka oikeasti kutsuu pythonin valmista tulostusfunktiota print. Kun rivi suoritetaan, tulostuu näytölle teksti "No hei.". Tämän jälkeen mennään seuraavalle riville, jossa on komento hei(). Python-tulkki näkee suluista että kyseessä on funktiokutsu ja etsii hei-nimisen funktion. Funktio hei suoritetaan, eli ajetaan komento print("No heipä hei!"), jota seuraa komento return. Komento return tarkoittaa tässä tapauksessa sitä, että palataan takaisin kohtaan josta funktiota kutsuttiin. Funktiokutsun hei() jälkeen ei ole muita komentoja, ja ohjelman suoritus päättyy.

Itsekirjoitetun funktion kutsuminen on helppoa, kirjoitetaan funktion nimi ja perään sulut ja puolipiste. Seuraavassa esimerkissä kutsutaan funktiota tervehdi ensin kerran ja sen jälkeen useita kertoja.

# ensin funktiomäärittelyt
def tervehdi():
    print("Terveisiä funktiosta tervehdi!")
    return

# ja sitten ohjelma joka käyttää funktioita!
print("Kokeillaan onnistuuko funktion kutsuminen:")
tervehdi()

print("Näyttää siltä, kokeillaan vielä:")
tervehdi()
tervehdi()
tervehdi()

Ohjelman suoritus saa aikaan seuraavan tulosteen:

Kokeillaan onnistuuko funktion kutsuminen:
Terveisiä funktiosta tervehdi!
Näyttää siltä, kokeillaan vielä:
Terveisiä funktiosta tervehdi!
Terveisiä funktiosta tervehdi!
Terveisiä funktiosta tervehdi!

Tässä siis huomionarvoista on, että koodin suoritus etenee siten, että pääohjelman rivit suoritetaan ylhäältä alas yksi kerrallaan. Koodirivin ollessa funktiokutsu, mennään suorittamaan funktion koodirivit jonka jälkeen palataan siihen kohtaan josta kutsu tapahtui, tai tarkemmin ottaen funktiokutsun jälkeiseen kohtaan.

Jatkossa kun esittelemme funktioita, emme erikseen mainitse että niiden täytyy sijaita omalla paikallaan. Funktioita ei esimerkiksi voi määritellä toisen funktion sisällä.

Tehtävä 1: Tekstin tulostus

Tee funktio tulostaTeksti, joka tulostaa tekstin "Alussa olivat suo, kuokka ja python."

Ohjelman tulostus:

Alussa olivat suo, kuokka ja python.

Tehtävä 2: Monta tulostusta

Laajenna edellistä ohjelmaasi siten, että pääohjelma kysyy käyttäjältä, montako kertaa teksti tulostetaan eli montako kertaa metodia kutsutaan.

Ohjelman tulostus:

Kuinka monta kertaa tulostetaan? 7
Alussa olivat suo, kuokka ja python.
Alussa olivat suo, kuokka ja python.
Alussa olivat suo, kuokka ja python.
Alussa olivat suo, kuokka ja python.
Alussa olivat suo, kuokka ja python.
Alussa olivat suo, kuokka ja python.
Alussa olivat suo, kuokka ja python.

Funktion parametrit

Funktiosta saa huomattavasti monikäyttöisemmän antamalla sille parametreja. Parametrit ovat muuttujia, jotka määritellään funktion ylimmällä rivillä funktion nimen jälkeen olevien sulkujen sisällä. Kun funktiota kutsutaan, sen parametreille annetaan arvot kutsuvaiheessa.

Seuraavassa esimerkissä määritellään parametrillinen funktio tervehdi, jolla on tekstityyppinen parametri nimi

def tervehdi(nimi):
  print("Hei " + nimi + ", terveiset funktiosta!")

Kutsutaan funktiota tervehdi siten, että parametrin nimi arvoksi asetetaan ensimmäisellä kutsulla Matti ja toisella kutsulla Arto.

# ensin funktiomäärittelyt
def tervehdi(nimi):
  print("Hei " + nimi + ", terveiset funktiosta!")

# sitten ohjelman toiminnallisuus
tervehdi("Matti")
tervehdi("Arto")
Hei Matti, terveiset funktiosta!
Hei Arto, terveiset funktiosta!

Aivan kuten kutsuttaessa pythonin valmista print-metodia, voi oman metodin kutsussa parametrina käyttää monimutkaisempaa ilmausta:

nimi1 = "Pihla"
nimi2 = "Toivanen"
tervehdi( nimi1 + " " + nimi2 )
ika = 24
tervehdi("Juhana " + str(ika) + " vuotta")
Hei Pihla Toivanen, terveiset funktiosta!
Hei Juhana 24 vuotta, terveiset funktiosta!

Molemmissa tapauksissa funktiolla on edelleen vain 1 parametri. Parametrin arvo lasketaan ennen funktion kutsumista. Ensimmäisessä tapauksessa parametrin arvo saadaan merkkijonokatenaationa nimi1 + " " + nimi2 joka siis on arvoltaan Antti Mikkola ja jälkimmäisessä tapauksessa merkkijonokatenaatiosta "Juhana " + str(ika) + " vuotta".

Lista parametrina

Listan käyttö parametrina onnistuu ilman ongelmia:

def tulostaAlkiot(lista):
  for alkio in lista:
    print(alkio)

luvut = [1, 2, 3, 4, 5]
tulostaAlkiot(luvut)
1
2
3
4
5

Huomaa että parametrin nimi funktion sisällä voi olla aivan vapaasti valittu, nimen ei tarvitse missään tapauksessa olla sama kuin kutsuvassa ohjelmassa. Edellä listaa kutsutaan metodin sisällä nimellä lista, metodin kutsuja taas näkee saman listan luvut-nimisenä.

Monta parametria

Funktiolla voidaan määritellä useampia parametreja. Tällöin metodin kutsussa parametrit annetaan samassa järjestyksessä.

def tervehdi(nimi, mistaTerveiset):
  print("Hei " + nimi + ", terveiset " + mistaTerveiset)
kuka = "Matti"
terveiset = "Kyröjoelta"

tervehdi(kuka, terveiset)
tervehdi(kuka, terveiset + " ja Kumpulasta")

Jälkimmäisessä tervehdi-funktion kutsussa toinen parametri muodostetaan katenoimalla muuttujaan terveiset teksti " ja Kumpulasta". Tämä suoritetaan ennen varsinaista funktion suoritusta.

Hei Matti, terveiset Kyröjoelta
Hei Matti, terveiset Kyröjoelta ja Kumpulasta

Funktio kutsuu toista funktiota

Pääohjelmamme, eli tässä vaiheessa alhaalla oleva koodi, ei suinkaan ole ainoa joka voi kutsua funktioita. Funktiot voivat kutsua myös toisiaan. Tehdään funktio tervehdiMontaKertaa, joka tervehtii käyttäjää useasti funktion tervehdi avulla:

def tervehdi(nimi):
  print("Hei " + nimi + ", terveiset funktiosta!")

def tervehdiMontaKertaa(nimi, kerrat):
  for i in range(kerrat):
    tervehdi(nimi)

tervehdiMontaKertaa("Antti", 3)
print("ja")
tervehdiMontaKertaa("Martin", 2)

Tulostuu:

Hei Antti, terveiset funktiosta!
Hei Antti, terveiset funktiosta!
Hei Antti, terveiset funktiosta!
ja
Hei Martin, terveiset funktiosta!
Hei Martin, terveiset funktiosta!

Tehtävä 3: Tähtien tulostus

Tee funktio tulostaTahtia, joka tulostaa annetun määrän tähtiä

tulostaTahtia(5)
tulostaTahtia(3)
tulostaTahtia(9)

Ohjelman tulostus:

*****
***
*********

Tehtävä 4: Viestin tulostus

Tee funktio tulostaViesti, joka tulostaa annetun viestin tähdillä reunustettuna. Käytä funktiossa apuna funktiota tulostaTahtia.

Tee ohjelma seuraavaan runkoon:

tulostaViesti("Tervetuloa!");
tulostaViesti("ABC");
tulostaViesti("Hei hei!");

Ohjelman tulostus:

***************
* Tervetuloa! *
***************
*******
* ABC *
*******
************
* Hei hei! *
************

Tehtävä 5: Viestien tulostus

Tee funktio tulostaViestit, joka tulostaa listassa annetut viestit tähdillä reunustettuina. Käytä funktiossa apuna funktiota tulostaViesti.

lista = ["Tervetuloa", "ABC", "Hei hei!"];
tulostaViestit(taulukko);

Ohjelman tulostus:

***************
* Tervetuloa! *
***************
*******
* ABC *
*******
************
* Hei hei! *
************

Tehtävä 6: Merkkien tulostus

Tee funktio tulostaMerkkeja, joka tulostaa annetun määrän annettuja merkkejä.

tulostaMerkkeja(5, 'A');
tulostaMerkkeja(3, 'B');
tulostaMerkkeja(9, 'C');

Ohjelman tulostus:

AAAAA
BBB
CCCCCCCCC

Funktiot ja muuttujien näkyvyys

Yritetään muuttaa funktion sisältä pääohjelman muuttujan arvoa.

def kasvataKolmella():
 x = x + 3

x = 1
kasvataKolmella()

print(x)

Ohjelma ei kuitenkaan toimi, sillä funktio ei näe muuttujaa x.

Yleisemminkin voi todeta, että pääohjelman muuttujat eivät suoraan näy muuttujat eivät näy funktioiden sisään, ja funktioiden muuttujat eivät näy muille funktioille tai pääohjelmalle. Yleisesti käytetty keino tiedon viemiseen funktioon on funktiolle annettavan parametrin käyttö.

Python mahdollistaa funktioiden määrittelyn siten, että ne näkevät funktioiden ulkopuolella määritellyt muuttujat avainsanan global avulla. Seuraavassa yllä esitetty esimerkki uudestaan, tällä kertaa globaalia muuttujaa käyttäen.

def kasvataKolmella():
 global x
 x = x + 3

x = 1
kasvataKolmella()

print(x)
4

Globaalien muuttujien käyttöä ohjelmissa kannattaa kuitenkin välttää, ja tyytyä tässä vaiheessa palauttamaan yksi arvo funktiota kohti.

Funktioiden paluuarvot

Funktio voi myös palauttaa arvon. Edellä olevissa esimerkeissä funktiot eivät palauttaneet mitään arvoa. Tämä on merkitty joko jättämällä return-lause pois funktiomäärittelystä, tai jättämällä return omalle rivilleen.

def tervehdi():
 print("Heippa vaan!")
 return

Arvon palauttavaa funktiota määriteltäessä annetaan funktiossa olevalle return-komennolle palautettava muuttuja. Seuraavassa funktio joka palauttaa aina luvun 10.

def palautetaanAinaKymppi():
 return 10

Jotta funktion kutsuja voisi käyttää paluuarvoa, tulee paluuarvo ottaa talteen muuttujaan:

luku = palautetaanAinaKymppi()

print("metodi palautti luvun " + str(luku))

Funktion paluuarvo siis sijoitetaan muuttujaan aivan kuin mikä tahansa muukin arvo. Paluuarvo voi toimia myös osana mitä tahansa lauseketta:

luku = 4 * palautetaanAinaKymppi() + palautetaanAinaKymppi() / 2 - 8

print("laskutoimituksen tulos " + str(luku))

Seuraavassa esimerkissä määritellään funktio summan laskemiseen. Tämän jälkeen funktiota käytetään laskemaan luvut 2 ja 7 yhteen, funktiokutsusta saatava paluuarvo asetetaan muuttujaan lukujenSumma.

def summa(eka, toka):
 return eka + toka

lukujenSumma = summa(2, 7);
print("Lukujen 2 ja 7 summa on " + str(lukujenSumma))

Laajennetaan edellistä esimerkkiä siten, että käyttäjä syöttää luvut.

def summa(eka, toka):
 return eka + toka


eka = int(input("Anna ensimmäinen luku: "))
toka = int(input("Anna toinen luku: "))

print("Luvut ovat yhteensä: " + str(summa(eka,toka)))

Kuten huomataan, funktion paluuarvoa ei tarvitse välttämättä sijoittaa muuttujaan, se voi olla osana tulostuslausetta aivan kuten mikä tahansa muukin arvo. Kannattaa kuitenkin huomata, että merkkijonoon liitettäessä kokonaislukumuuttujat tulee muuttaa myös teksti- tai merkkijonotyyppisiksi funktiokutsulla str.

Seuraavassa esimerkissä funktiota summa kutsutaan kokonaisluvuilla, jotka saadaan summa-metodin paluuarvoina.

def summa(eka, toka):
 return eka + toka

a = 3
b = 2

summienSumma = summa(summa(1,2), summa(a,b))
# 1) suoritetaan sisemmät metodit:
#    summa(1,2) = 3   ja summa(a,b) = 5
# 2) suoritetaan ulompi metodi:
#    summa(3,5) = 8

print(summienSumma)
8

Funktion omat muuttujat

Seuraava funktio laskee syötteinään saamiensa luvun keskiarvon. Metodi käyttää apumuuttujia summa ja ka. Metodin sisäisen muuttujan määrittely tapahtuu tutulla tavalla.

def keskiarvo(luku1, luku2, luku3):
 summa = luku1 + luku2 + luku3
 ka = summa/3.0

 return ka

Tehtävä 7: Lukujen summa

Tee funktio summa, joka laskee listan lukujen summan.

Tee metodi seuraavaan runkoon:

lista = [3, 2, 7, 2]
print "Summa: " + str(summa(lista))

Ohjelman tulostus:

Summa: 14

Tehtävä 8: Lukujen keskiarvo

Tee funktio keskiarvo, joka laskee listan lukujen keskiarvon. Funktiossa kannattaa käyttää apuna funktiota summa.

lista = [3, 2, 7, 2]
print("Keskiarvo: " + str(keskiarvo(lista)))

Ohjelman tulostus:

Keskiarvo: 3.5

Tehtävä 9: Onko luku listassa?

Tee ohjelma, joka kertoo, onko käyttäjän antama luku listassa.

Lista määritellään koodin alussa seuraavasti:

luvut = [7, 2, 4, 8]

Esimerkkitulostuksia:

Anna luku: 4
Luku on listassa.
Anna luku: 3
Lukua ei ole listassa.