Funktiot
Funktiot ovat koodausta helpottava juttu, joiden avulla pystyy selkeyttämään koodia, vähentämään toistoa ja jakamaan koodia osiin. Niitä kannattaa opetella tekemään, koska nätisti osiin jaetun koodin kanssa on paljon helpompaa ja mukavempaa työskennellä :)
Funktiot matematiikassa
Muistellaan, mitä funktio tarkoittaa matematiikassa. Funktio ottaa jonkun luvun (tai monta lukua), ja laskee niiden perusteella jonkun tuloksen:
Esimerkiksi tämä funktio nimeltä f
laskee mitä on luku kerrottuna kahdella. Funktio
määritellään matematiikassa näin:
f(x) = 2x
Funktiolle annettavaa lukua kuvaava x-muuttuja nimetään funktion nimen vieressä olevien sulkujen sisällä, ja sitten sitä käytetään funktion laskulausekkeessa kohdissa, johon halutaan sijoittaa funktiolle annettu arvo:
f(3) = 2*3 = 6
x-muuttujaa voidaan käyttää useassa eri funktiossa argumentin nimenä, ja tämä ei haittaa eikä vaikuta mitenkään muihin funktioihin.
Funktiot Pythonissa
Myös Pythonissa pystyy tekemään funktioita. Niillä pystyy tekemään paljon muitakin juttuja kuin numeroiden käsitteleminen, mutta jos funktioiden käsittely sujuu matematiikassa, niin ohjelmointifunktioiden vertaaminen matikkafunktioihin saattaa auttaa ymmärtämään niitä paremmin.
Määritellään yllä oleva funktio f
Pythonissa:
def f(x):
return 2*x
Käydään koodi läpi rivi riviltä. Ensimmäinen sana, def
, merkitsee sitä, että ollaan
määrittelemässä uutta funktiota (def = define = määrittele). Sitten keksitään funktiolle nimi,
tässä tapauksessa f
(mutta voi olla mikä tahansa, tässä parempi nimi voisi olla tuplaa
).
Sitten sulkujen sisällä määritellään, mitä parametreja funktio ottaa. Parametri siis tarkoittaa
funktion ottamaa arvoa jota se käsittelee jotenkin. Tässä esimerkissä funktio ottaa vain yhden
parametrin, joka on numero jonka se tuplaa. Tälle parametrillekin voi antaa minkä tahansa
nimen.
Kaksoispiste tarkoittaa, että seuraavalta riviltä alkaa funktion oma lohko.
Mistä se parametri oikeen tulee???
Parametri luodaan/määritellään juuri tuolla ekalla rivillä. Eli kun kirjoitat sulkujen sisään parametreja, niin siinä määrittelet niiden nimet (ja niiden olemassaolon).
Jos olet kirjoittanut def-riville tietyt parametrit, niin sellaisia parametreja funktio odottaa saavansa, ja jos yrität antaa funktiolle enemmän tai vähemmän argumentteja kuin def-rivillä on määritelty, niin siitä tulee errori.
Funktiolohkon sisällä oleva koodi määrittelee, mitä funktio oikein tekee. Tässä funktiossa
sattuu olemaan vain yksi rivi, return 2*x
. Return (suomeksi palauta) tarkoittaa sitä, että
funktio loppuu, ja jokin arvo palautetaan funktion tuloksena (tässä tapauksessa 2*x
).
Nyt kun funktio on määritelty, niin sitä voi käyttää esimerkiksi näillä tavoilla:
print(f(100))
tuplattava = 5
print(tuplattava, "tuplattuna:", f(tuplattava))
for i in range(f(2)):
print(i)
200
5 tuplattuna: 10
0
1
2
3
Funktion käyttämistä näin sanotaan kutsumiseksi
. Eli tämä on funktiokutsu: f(2)
. Vaikka
funktio ei ottaisi yhtään parametria, niin sen kutsuminen vaatii silti sulut: print()
. Jos
kirjoitat koodiin pelkästään funktion nimen ilman sulkuja, niin se ei tee mitään.
Jos osaat jo käyttää muuttujia koodin seassa, niin funktiokutsu toimii vähän samalla tavalla. Vertaa näitä:
# aika turha funktio joka vaan palauttaa arvon 5
def viis():
return 5
# muuttuja jonka arvo on 5
viitonen = 5
print(viis())
print(viitonen)
print(viis() + 2)
print(viitonen + 2)
5
5
7
7
Argumentti? Parametri?
Sanoja parametri ja argumentti käytetään usein sekaisin, mutta jos tarkkoja ollaan, niin parametri tarkoittaa def-rivillä funktion sulkujen sisällä määriteltyä muuttujaa, kun taas argumentti tarkoittaa funktiolle käsiteltäväksi annettavaa oikeaa arvoa.
# tuossa luku on parametri
def tuplaa(luku):
return luku * 2
# tuossa 5 on argumentti
print(tuplaa(5))
Funktio voi käsitellä mitä tahansa datatyyppejä. Tässä esimerkki tuplen käsittelystä. Jos et vielä tiedä mikä on tuple, niin se on vähän niin kuin lista, mutta sitä ei pysty muokkaamaan luomisen jälkeen (eli sen yksittäisiä alkioita ei pysty muuttamaan tai poistamaan). Tuple on kätevä tapa laittaa monta tiedonpalasta yhdeksi paketiksi.
# tässä oletetaan, että tuote-parametriksi annetaan tuple,
# joka sisältää nämä alkiot:
# 0. tuotteen nimi (merkkijono)
# 1. tuotteen määrä varastossa (kokonaisluku)
# 2. tuotteen kuvaus (merkkijono)
def muunna_merkkijonoksi(tuote):
# otetaan selkeyden vuoksi tuplen alkiot muuttujiin
nimi = tuote[0]
maara = str(tuote[1])
kuvaus = tuote[2]
# muodostetaan alkioista yksi merkkijono
tulos = ""
# \n tarkoittaa rivinvaihtomerkkiä
tulos += nimi + "\n"
tulos += "Varastossa: " + maara + " kpl\n"
tulos += kuvaus
return tulos
Tässä funktiossa on paljon enemmän rivejä kuin tuplaamisfunktiossa. Ajattele, jos tästä ei tekisi funktiota, vaan tuplen käsittelyn kirjoittaisi suoraan koodin sekaan. Jos merkkijonoksi muuntamista tarvittaisiin koodissa monessa kohtaa, niin koodiin tulisi paljon extrarivejä, joissa sanottaisiin täysin sama asia. Lisäksi koodista tulisi sekavampi. Tämän takia koodia kannattaa jakaa funktioihin, etenkin jos samaa toiminnallisuutta tarvitaan useammin kuin kerran.
Tässä vielä esimerkki tämän funktion käytöstä, jos se jäi epäselväksi.
tuotteet = [
("Paita", 55, "Tosi hieno paita"),
("Kirja", 38, "Luontokuvia sisältävä kirja"),
("Luistimet", 11, "Valkoiset taitoluistimet")
]
for tuote in tuotteet:
print(muunna_merkkijonoksi(tuote))
print("-----")
Paita
Varastossa: 55 kpl
Tosi hieno paita
-----
Kirja
Varastossa: 38 kpl
Luontokuvia sisältäviä kirja
-----
Luistimet
Varastossa: 11 kpl
Valkoiset taitoluistimet
-----
Funktion ei tarvitse palauttaa mitään
Joskus tarvitaan funktiota, joka vain suorittaa tietyt koodirivit, mutta sillä ei ole mitään
tulosta, jonka voisi palauttaa. Esimerkki tällaisesta funktiosta on print
. Printin tehtävä on
pelkästään tulostaa näkyviin sille annetut argumentit.
Testataan mitä tapahtuu, jos printin tuloksen yrittää tulostaa:
# tulostetaan print-kutsun tulos (paluuarvo)
print(print("Moikka!"))
Moikka!
None
Print-funktion tulos on siis None (none = ei mitään). Jos et laita kirjoittamasi funktion sisään
lainkaan returnia, tai kirjoitat pelkästään return
ilman mitään arvoa, niin funktiosi toimii
samalla tavalla kuin print yllä. Siitä tulee siis None.
Sisäänrakennetut funktiot
Pythonissa on monia sisäänrakennettuja funktioita. Tässä muutama esimerkki näistä funktioista.
len
Funktio len
ottaa argumentiksi merkkijonon tai listan, ja palauttaa sen pituuden.
nimi = input("Kirjoita nimesi: ")
print(f"Nimesi on {len(nimi)} merkkiä pitkä.")
Funktio print
ottaa argumentiksi mitä tahansa dataa, ja tulostaa sen. Printille voi antaa
montakin argumenttia, jolloin se tulostaa ne välilyönnillä erotettuna.
print("Moikka")
print(["a", "b", "c"])
print("a", "b", "c", 1, 2, 3)
Moikka
['a', 'b', 'c']
a b c 1 2 3
min ja max
min
voi ottaa argumentiksi kaksi tai enemmän numeroita, tai listan numeroita. Se palauttaa
luvuista pienimmän. max
on samanlainen funktio joka palauttaa suurimman luvun.
num1 = int(input("Anna numero: "))
num2 = int(input("Anna toinen numero: "))
suurempi = max(num1, num2)
print(f"Luvuista suurempi on {suurempi}.")
Sisäkkäiset funktiokutsut
Funktioita pystyy kutsumaan sisäkkäin niin monta kuin haluaa. Siis kutsutaan yhtä funktiota, jonka palautusarvo annetaan argumentiksi toiselle funktiolle, ja sitten toisen funktion palautusarvo annetaan argumentiksi kolmannelle funktiolle ja niin edelleen. Edellisen esimerkin voi kirjoittaa vaikka kokonaan yhdelle riville sisäkkäisten funktiokutsujen avulla:
print(f"Luvuista suurempi on {max(int(input('Anna numero: ')), int(input('Anna toinen numero: ')))}.")
Kuitenkin liian monta funktiokutsua sisäkkäin näyttää todella sekavalta, joten niitä ei kannata käyttää liikaa (tässä esimerkissä on f-stringikin sekoittamassa).
Tehtävät
Kirjoita funktio, joka ottaa argumentiksi jotain tekstiä ja tulostaa sen, ja lisäksi sen ylä- ja alapuolelle jonkin tekstistä tehdyn kuvion/reunuksen. Tulosta funktiolla jotain tekstiä.
def hieno_printtaus(teksti):
print("-----~.O.~-----")
print(" ", teksti)
print("------.v.------")
hieno_printtaus("kehys :)")
Kirjoita tämä matemaattinen funktio Pythonina:
f(x) = 3x + 5
Tulosta arvo f(10)
viime tehtävässä tehdyllä printtausfunktiolla.
def f(x):
return 3*x + 5
hieno_printtaus(f(10))
Kirjoita funktio onko_parillinen, joka ottaa argumentiksi numeron ja palauttaa totuusarvon,
joka kertoo, onko luku parillinen. Vinkki: käytä jakojäännös- eli modulo-operaattoria (%
).
Kysy käyttäjältä lukua, ja kutsu funktiota. Jos luku on parillinen, niin tulosta jokin tietty viesti. Tulosta jokin toinen viesti jos luku on pariton.
def onko_parillinen(luku):
if luku % 2 == 0:
return True
else:
return False
num = int(input("Anna luku: "))
if onko_parillinen(num):
print("Luku on parillinen.")
else:
print("Luku on pariton.")
Lyhyempi tapa kirjoittaa funktio:
def onko_parillinen(luku):
return luku % 2 == 0