Python 3/Funktio
Funktio on yleensä kokonaisuus, joka suorittaa yhtä toimintoa tai vastaa vastaa yhdestä ohjelman tehtävästä.
Kun funktio on kiinni oliossa, kutsutaan sitä metodiksi. Metodeita käsitellään osassa Luokka.
Funktion luominen
[muokkaa | muokkaa wikitekstiä]Funktio luodaan def avainsanalla.
Esimerkki yksinkertaisesta funktiosta
def hello():
print("Hei")
# kutsutaan hello() funktiota
hello()
Tuloste
Hei
Parametrit
[muokkaa | muokkaa wikitekstiä]Funktiolla voi olla parametreja, joita sille annetaan.
Esimerkki funktiosta, jolle annetaan parametrina name-muuttuja.
def hello(name):
print("Hei " + name)
name = "Peikko"
hello(name)
name = "Matti"
hello(name)
Tuloste
Hei Peikko Hei Matti
Funktion parametrille voi antaa oletusarvon, jota käytetään, jos mitään arvo ei anneta.
def hello(name="Keke"):
print("Hei " + name)
name = "Peikko"
hello(name)
hello()
Tuloste
Hei Peikko Hei Keke
Funktiota kutsuttaessa voidaan parametrit antaa myös nimellä. Jos argumentit annetaan parametrin nimellä, pitää mahdolliset nimettömät argumentit antaa ensin.
hello(name="Peikko")
Tuloste
Hei Peikko
Usean arvon palauttaminen
[muokkaa | muokkaa wikitekstiä]Funktiosta voi palauttaa useita arvoja luettelemalla ne pilkulla erotettuna.
def jaa(jaettava, jakaja):
return jaettava // jakaja, jaettava % jakaja
Paluuarvo on silloin itse asiassa monikko (tuple). Funktion kutsusta paluuarvon voi lukea yhtenä monikkona tai erillisinä arvoina.
>>> tulos = jaa(5, 2)
>>> tulos
(2, 1)
>>> osamäärä, jakojäännös = jaa(5, 2)
>>> osamäärä
2
>>> jakojäännös
1
Paikalliset funktiot
[muokkaa | muokkaa wikitekstiä]Funktiota ei tarvitse määritellä tiedoston ylimmällä tasolla, vaan sen voi määritellä myös toisen funktion sisällä.
def lajittele(lista):
"""Lajittelee annetut sanat päätteen mukaan.
"""
def apu(sana):
return "".join(reversed(list(sana)))
return sorted(lista, key=apu)
print(lajittele(["kana", "lakana", "vakava", "takana", "pakana", "sakara", "pakara", "hana"]))
Tuloste
['hana', 'kana', 'lakana', 'pakana', 'takana', 'pakara', 'sakara', 'vakava']
Yllä funktio apu
annettiin parametrina sorted
-funktiolle. Funktioviittauksen voi tällä tavalla antaa argumenttina, tallentaa muuttujaan tai palauttaa funktiosta. Funktiota voi kutsua muuttujan kautta samalla tavalla kuin sen varsinaisella nimelläkin.
>>> lajittelu = lajittele
>>> lajittelu(["muusi", "musti", "uusi", "bluussi"])
['bluussi', 'uusi', 'muusi', 'musti']
Paikallisen funktion voi myös palauttaa funktiosta. Paikallisella funktiolla on pääsy kaikkiin isäntäfunktion paikallisiin muuttujiin ja parametriarvoihin myös palauttamisen jälkeen.
def tee_lisääjä(lisättävä):
def kääre(luku):
return luku + lisättävä
return kääre
lisää_yksi = tee_lisääjä(1)
print(lisää_yksi(2))
Tulostaa
3
Tyyppivihjeet
[muokkaa | muokkaa wikitekstiä]Funktion parametrien ja paluuarvon tyypin voi merkitä tyyppivihjeillä. Tyyppivihjeet ovat vain ohjelmoijalle tarkoitettuja. Python ei tarkista niitä mitenkään. Eräissä sovelluskehitysympäristöissä on kuitenkin automaattinen tarkistus.
Parametrin tyyppi kirjoitetaan kaksoispisteen jälkeen. Funktion palautusarvo merkitään ennen funktion rungon avaavaa kaksoispistettä nuolen (->) jälkeen.
def tee_tunnus(nimi: str, numero: int) -> str:
return f'{nimi} ({numero})'
Taulukot merkitään kirjoittamalla taulukon alkioiden tyyppi hakasulkujen [] sisään.
def lajittele(luvut: [int]) -> [int]:
pass
Lambdat
[muokkaa | muokkaa wikitekstiä]Yhden rivin mittaisia nimettömiä funktioita voi tehdä lambda
-avainsanalla. Lambda-sanan jälkeen luetellaan parametrit ilman sulkuja. Kaksoispisteen jälkeen tulee yhden lauseen mittainen lambdan runko. Lambdoja käytetään lähinnä, kun annetaan toiselle funktiolle parametrina funktio, josta se kutsuu. Tätä käsitellään enemmän funktionaalista ohjelmointia käsittelevässä luvussa.
tiedot = [
{ 'nimi': 'Hanski', 'ikä': 33 },
{ 'nimi': 'Väiski', 'ikä': 24 },
{ 'nimi': 'Hiski', 'ikä': 45 },
]
>>> iät = map(lambda x: x['ikä'], tiedot)
>>> list(iät)
[33, 24, 45]
Vaihteleva määrä parametreja
[muokkaa | muokkaa wikitekstiä]Joskus on hyödyllistä tehdä funktio, jota voi kutsua vaihtelevalla määrällä argumentteja. Esimerkiksi Pythonin sisäänrakennetuille funktioille print
, min
ja max
voi antaa miten monta arvoa tahansa.
Kun funktion määrittelyssä merkitään parametrin eteen asteriski (*), kokoaa parametri kaikki loput funktiolle annetut argumentit yhteen muuttujaan, joka on tyypiltään monikko (tuple).
>>> def f(*args):
... print(args)
...
>>> f(1, 2, 3, 4)
(1, 2, 3, 4)
Esimerkki: annettujen lukujen keskiarvon laskeva funktio.
def keskiarvo(*luvut):
tulos = 0
for luku in luvut:
tulos += luku
return tulos / len(luvut)
>>> keskiarvo(1, 2, 3, 4, 5, 6, 7, 8)
4.5
Asteriskilla merkityn parametrin lisäksi voi sitä ennen olla muita tavallisia parametreja.
def yhdistä_luetteloksi(pre, suf, *arvot):
tulos = []
for arvo in arvot:
tulos.append(pre + arvo + suf)
return ", ".join(tulos)
>>> yhdistä_luetteloksi("[[", "]]", "a", "b", "c")
'[[a]], [[b]], [[c]]'
Myös nimetyille argumenteille on mahdollista käyttää ne kokoavaa parametria. Tätä merkitään kahdella asteriskilla. Funktion sisällä tällainen nimetyt argumentit kokoava parametri on tyypiltään dict eli sanakirja. Myös **
kokoaa loput nimetyt argumentit, sitä ennen parametriluettelossa voi olla muita parametreja, joita ei koota yhteen.
def muotoile_tiedot(**tiedot):
tulos = []
for k, v in tiedot.items():
tulos.append(f"{k + ':': <10} {v}")
return "\n".join(tulos)
>>> print(muotoile_tiedot(Nimi="Korkki Korhonen", Ikä=30, Ammatti="sellisti"))
Nimi: Korkki Korhonen
Ikä: 30
Ammatti: sellisti
Jos käytetään molempia kokoavia muotoja, on parametrien järjestys seuraava:
[nimetön 1], ... [nimetön n], [*nimettömät kokoava], [oletusarvollinen 1], ... [oletusarvollinen n], [**nimetyt kokoava]
tai
[nimetön 1], ... [nimetön n], [oletusarvollinen 1], ... [oletusarvollinen n], [*nimettömät kokoava], [**nimetyt kokoava]
Listan tai monikon muuttaminen funktion argumenteiksi
[muokkaa | muokkaa wikitekstiä]Operaattoreita *
- ja **
voi paitsi käyttää funktion argumenttien kokoamiseen, myös muuttamaan lista, monikko tai sanakirja argumenteiksi funktiota kutsuttaessa.
Operaattorilla *
voi muuttaa listan, monikon tai muun sekvenssityypin sisällön funktion argumenteiksi.
>>> keskiarvo(*[1, 2, 3, 4, 5, 6, 7, 8])
4.5
Operaattorilla **
voi muuttaa sanakirjan funktion nimetyiksi argumenteiksi.
>>> tiedot = { "Nimi": "Korkki Korhonen", "Ikä": 30, "Ammatti": "sellisti" }
>>> print(muotoile_tiedot(**tiedot))
Nimi: Korkki Korhonen
Ikä: 30
Ammatti: sellisti
>>> lista = [1, 2, 3, 4, 5, 6]
>>> print(*lista)
1 2 3 4 5 6
Funktiossa ei tarvitse olla *-parametria tai **-parametria, vaan argumenteiksi muuttaminen toimii minkä tahansa funktion kanssa, mutta silloin pitää olla tarkkana, että arvoja on oikea määrä tai niillä on oikeat nimet.
def ynnää(luku1, luku2):
return luku1 + luku2
>>> arvot = (5, 6)
>>> ynnää(*arvot)
11
>>> arvot = { 'luku1': 7, 'luku2': 8 }
>>> ynnää(**arvot)
15
Funktion kaikki parametrit voi siten siepata käyttämällä sekä *-parametria että **-parametria. Siepatut parametrit voi välittää toiselle funktiolle *- ja **-operaattoreilla.
def f(*args, **kwargs):
return g(*args, **kwargs)
Dekoraattorit
[muokkaa | muokkaa wikitekstiä]Olemassa olevan funktion toimintaa voi muuttaa toisen funktion avulla. Tällaista muuttavaa funktiota kutsutaan dekoraattoriksi.
Dekoraattori on funktio, joka ottaa parametrikseen funktion, ja palauttaa uuden funktion, joka kutsuu varsinaista funktiota. Tässä välissä dekoraattori voi tehdä muita toimintoja. Alkuperäinen funktio siis ikäänkuin kääritään toiseen funktioon. Kun kääreelle annetaan sama nimi kuin alkuperäiselle funktiolle, kutsutaan alkuperäisen sijasta aina tätä käärefunktiota. Tarkalleen ottaen dekoraattorin ei tarvise olla funktio, vaan se voi olla mikä tahansa kutsuttavissa oleva (callable) olio.
Alla olevassa esimerkissä dekoraattori logitus tulostaa funktion parametrit ennen funktion kutsua ja paluuarvon funktion kutsumisen jälkeen. Kääre on funktio joka korvaa alkuperäisen hae_tervehdys -funktion. (Tässä on käytetty *args- ja **kwargs-parametreja, jotta dekoraattori toimii kaikilla funktioilla. Yhtä hyvin voisi käyttää tavallisia parametreja.)
def logitettu(funktio):
def kääre(*args, **kwargs):
print(f"Kutsutaan funktiota {funktio.__name__}; parametrit", args, kwargs)
ret = funktio(*args, **kwargs)
print(f"Kutsuttiin funktiota {funktio.__name__}; tulos", ret)
return ret
return kääre
def ynnää(luku1, luku2):
return luku1 + luku2
ynnää = logitettu(ynnää)
print(ynnää(2, 3)) # Tässä kutsutaan käärefunktiota, joka on nyt alkuperäisen funktion nimellä
Tulostaa
Kutsutaan funktiota ynnää; parametrit (2, 3) {} Kutsuttiin funktiota ynnää; tulos 5 5
Funktion voi kääriä dekoraattoriin määrittelyn yhteydessä erityisellä @-syntaksilla. Esimerkiksi yllä voitaisiin rivin
hae_tervehdys = logitus(hae_tervehdys)
sijaan käyttää funktion hae_tervehdys määrittelyssä merkintää
@logitettu
def ynnää(luku1, luku2):
return luku1 + luku2
Dekoraattori parametreilla
[muokkaa | muokkaa wikitekstiä]Dekoraattorin voi muodostaa myös funktiolla annettujen parametrien mukaiseksi. Dekoraattorin tilalle @-lausekkeeseen laitetaan tilalle funktiokutsu, joka palauttaa dekoraattorin (joka palauttaa käärefunktion). Havainnollistetaan asiaa tekemällä dekoraattorin, joka lisää lainausmerkit kohdefunktion palauttaman arvon ympärille. Halutut lainausmerkit voi antaa tapauskohtaisesti. Aloitamme tekemällä kuitenkin samanlaisen yksinkertaisen dekoraattorin kuin aiemmin.
def siteerattu(funktio):
alkumerkki = '”'
loppumerkki = '”'
def kääre(*args, **kwargs):
return alkumerkki + funktio(*args, **kwargs) + alkumerkki
return kääre
@siteerattu
def hae_tervehdys(nimi):
return f'Terve {nimi}!'
print(hae_tervehdys("Jykä"))
Tulostaa
”Terve Jykä!”
Seuraavaksi lisäämme edellisen siteerattu-funktion ympärille funktion, joka palauttaa sen. Funktio siteerattu käyttää tee_siteerattu-funktiolle annettuja argumentteja omassa koodissaan.
def tee_siteerattu(alkumerkki, loppumerkki):
def siteerattu(funktio):
def kääre(*args, **kwargs):
return alkumerkki + funktio(*args, **kwargs) + loppumerkki
return kääre
return siteerattu
@tee_siteerattu('«', '»')
def hae_tervehdys(nimi):
return f'Terve {nimi}!'
print(hae_tervehdys("Jykä"))
Tulostaa
«Terve Jykä!»
Dekoraattoreita voi myös pinota useita päällekkäin.
Pythonissa on olemassa joitakin valmita dekoraattoreita. Esimerkiksi olion gettereiden ja setteriden luomiseen käytetyt @property
ja @x.setter
sekä @staticmethod
. Näitä käsitellään olio-ohjelmoinnin yhteydessä. Mitä tahansa funktiota, joka ottaa funktion parametrikseen voi käyttää dekoraattorina.
Aiheesta muualla
[muokkaa | muokkaa wikitekstiä]- Python-kielisen_ohjelmoinnin_perusteet (Wikiopiston opintopiirin opiskeluohjeita)
Johdanto: | |
---|---|
Tietotyypit ja tietorakenteet: |
Luvut - Merkkijonot - Lista - Monikko (tuple) - Sanakirja - Joukko (set) |
Ohjausrakenteet | |
Muut kielen rakenteet: |
Moduuli - Luokka - Funktio - Virheidenhallinta - Tiedosto |
Graafinen käyttöliittymä: | |
Harjoitustehtäviä: | |
Lisätiedot ja lähteet: |