Funktiot

Tähän mennessä olemme jo käyttäneet muutamia Pythonin sisäänrakennettuja funktioita kuten print, input ja round

  • print-funktio tulostaa sille suluissa annetut tekstit ja muuttujat
  • input-funktio tulostaa sille annetun tekstin ja palauttaa käyttäjän syöttämän merkkijonon
  • round-funktio palauttaa haluttuun tarkkuuteen pyöristetyn liukuluvun

Lisäksi olemme käyttäneet funktioita tyyppimuunnoksiin:

tilavuus = float(input("Anna tilavuus:\n"))

Yllä float-funktio tekee siis tyyppimuunnoksen merkkijonosta liukuluvuksi.

Pythonissa on useita sisäänrakennettuja funktioita ja erilaiset ohjelmakirjastot sisältävät lukuisia funktioita eri käyttötarkoituksiin. 

Tällä kierroksella opit kirjoittamaan omia funktioita. Niiden avulla toistuvien tehtävien suorittaminen helpottuu ja koodin rakenne pysyy selkeämpänä.

Funktioiden määritteleminen, parametrit ja paluuarvot.

Funktiolla on tavallisesti joku selkeä tehtävä, esimerkiksi tietty laskutoimitus. Funktioita kutsutaan joskus myös aliohjelmiksi.

Funktiota käytettäessä sille voidaan antaa sulkujen sisällä parametreja. Esimerkiksi funktiokutsussa 

print("H2O")

parametri on merkkijono "H2O". Tässä esimerkissä taas parametreja ovat kokonaisluvut 1, 2 ja 3:

print(1, 2, 3)

Funktiolla voi olla paluuarvo. Esimerkiksi tässä esimerkissä round-funktion parametri on liukuluku 2.123 ja paluuarvo on liukuluku 2.1:

tulos = round(2.123)
Esimerkki 1

Tarkastellaan ohjelmaa, jossa luodaan funktio tuplaa ja kutsutaan sitä pääohjelmasta: 

# Määritellään ensin funktio tuplaa käyttäen def-avainsanaa
# Funktio ajetaan vasta, kun sitä kutsutaan pääohjelmasta
# Huomaa, miten funktion sisältö on sisennetty
def tuplaa(luku):    
    return luku * 2

# Pääohjelma alkaa tästä (ei sisennystä)
# Kutsutaan funktiota "tuplaa"
iso_luku = tuplaa(12)
print(iso_luku)

  • Funktio määritellään avainsanalla def, jonka jälkeen tulee funktion nimi (tuplaa)
  • tuplaa-funktiolla on yksi parametri, jonka nimi on luku (suluissa funktion nimen jälkeen)
  • return-avainsanan jälkeen tulee funktion paluuarvo (tässä tapauksessa parametri luku kerrottuna kahdella).

Ohjelman suoritus etenee rivi riviltä näin:

  1. Ensin suoritetaan pääohjelman rivi "iso_luku = tuplaa(12)". Koska rivillä kutsutaan funktiota tuplaa, ohjelman suoritus hyppää funktion sisälle. Parametrina on kokonaisluku 12.
  2. Funktion tuplaa ainoa rivi palauttaa parametrin luku arvon kerrottuna kahdella. Eli tässä tapauksessa 12 * 2
  3. return-avainsanan jälkeen suoritus jatkuu pääohjelmassa, jossa muuttuja iso_luku saa funktion paluuarvon 12 * 2, eli 24.
  4. Lopuksi tulostetaan kokonaisluku 24
Esimerkki 2

Tarkastellaan toista esimerkkiohjelmaa, jossa määritellään funktio tiheys ja käytetään sitä:

# Määritellään ensin funktio tiheys käyttäen def-avainsanaa
def tiheys(tilavuus, massa):
    # Funktio palauttaa kappaleen tiheyden
    # Funktion parametrit:
    #   Tilavuus: Kappaleen tilavuus (m^3)
    #   Massa:    Kappaleen massa (kg)
    # Jos funktiota kutsutaan epäfysikaalisella parametrilla, se 
    # tulostaa virheilmoituksen ja palauttaa arvon -1
    
    # Tarkistetaan ensin, että parametrit ovat fysikaalisesti mielekkäät
    if tilavuus <= 0:
        print("Virheellinen tilavuus")
        return -1
    elif massa <= 0:
        print("Virheellinen massa")
        return -1
    else:
        return massa / tilavuus

# Pääohjelma alkaa tästä (ei sisennystä)
# Kysytään arvot käyttäjältä
V = float(input("Anna kappaleen tilavuus (m^3):\n"))
m = float(input("Anna kappaleen massa (kg):\n"))
# Kutsutaan tiheys-funktiota annetuilla arvoilla
rho = tiheys(V, m)
# Tarkistetaan funktion paluuarvo. -1 tarkoittaa virhettä
if rho == -1:
    print("Tiheyden laskeminen epäonnistui")
else:
    print("Kappaleen tiheys on:", round(rho,3), "kg/m^3")

  • Tässä esimerkissä funktion tiheys suorittama laskutoimitus oli hyvin yksinkertainen.
  • Oikeissa ohjelmissa funktio voi suorittaa hyvinkin monimutkaisia operaatioita. Nämä monimutkaiset operaatiot kannattaa nimenomaan "paketoida" funktioihin
  • Koodin testaaminen ja virheiden etsiminen on helpompaa, kun se on jaettu funktioihin
  • Hyvin kirjoitetut ja dokumentoidut funktiot ovat helposti uudelleenkäytettävissä uusissa ohjelmissa

Esimerkki 3

Tässä tapauksessa meillä on funktio kysy_suure, joka hoitaa vuorovaikutuksen käyttäjän kanssa:

# Ensin määritellään funktio. Sitä kutsutaan pääohjelmasta.
def kysy_suure(suure):
    # Funktio kysyy liukulukua käyttäjältä, kunnes annettu arvo on > 0
    # Parametri suure on merkkijono, esim. "massa (g)"
    arvo = -1
    while arvo <= 0: 
        arvo = float(input("Anna " + suure + ":\n"))
        if arvo > 0:
            return arvo
        else:
            print("Virheellinen arvo")
        
# Pääohjelma alkaa täältä
# Kysytään massa ja moolimassa funktion kysy_suure avulla
moolimassa = kysy_suure("moolimassa (g/mol)")
massa = kysy_suure("massa (g)")
n = massa / moolimassa
print("Ainemäärä on", round(n,2), "mol")

Etuna on se, että virheellisten arvojen käsittely while-silmukan avulla tarvitsee kirjoittaa vain kerran. Jos emme käyttäisi funktiota, ratkaisu voisi näyttää tältä:

# Luetaan moolimassa
arvo = -1
while arvo <= 0: 
    arvo = float(input("Anna moolimassa (g/mol):\n"))
    if arvo > 0:
        moolimassa = arvo
    else:
        print("Virheellinen arvo")
  
# Luetaan massa
arvo = -1
while arvo <= 0: 
    arvo = float(input("Anna massa (g):\n"))
    if arvo > 0:
        massa = arvo
    else:
        print("Virheellinen arvo")
        
n = massa / moolimassa
print("Ainemäärä on", round(n,2), "mol")

  • Jälkimmäinen ratkaisu ei ole kovin paljon ensimmäistä pidempi, mutta kuvittele tilanne, jossa suureita pitäisi lukea kymmenen kappaletta. Tällöin funktion kysy_suure käyttäminen helpottaa koodin kirjoittamista merkittävästi. 
  • Jos koodiin täytyisi tehdä joku muutos, esimerkiksi vaihtaa virheilmoitus "Virheellinen arvo" joksikin muuksi, ensimmäisessä kysy_suure-funktiota käytettäessä riittää funktion kysy_suure päivittäminen, eikä muutosta tarvitse tehdä moneen paikkaan.

Tehtävä 2.1.1

Tehtävä 2.1.2