Kirjoittaja: Antti Laaksonen (2009).
⚠ Huomio! Tämä opas on vanhentunut. Oppaan sisältöön ei voi enää luottaa. Opas on säilytetty vain sen historiallisen arvon vuoksi. ⚠
Opassarjan kuluessa on tutustuttu moneen hyödylliseen funktioon. Esimerkiksi funktio str muuttaa arvon merkkijonoksi, funktio range muodostaa lukuja sisältävän listan, funktio len laskee merkkijonon merkkien määrän ja funktio min etsii listan pienimmän luvun.
Tämän oppaan aiheena on omien funktioiden laatiminen. Funktiot selventävät koodin rakennetta, koska niiden avulla eri puolilla ohjelmaa tarvittava samanlainen koodi täytyy kirjoittaa vain kerran. Lisäksi hyvin suunniteltuja funktioita voi käyttää uudestaan tulevissa ohjelmissa.
Oppaan ensimmäinen funktio tulostaa tekstin laatikon sisään. Seuraavaksi nähdään, mitä hyötyä funktiosta on tässä tapauksessa.
Seuraava ohjelma tulostaa tekstin laatikkoon:
# -*- coding: latin-1 -*- print "*" * 15 print "*", "Tervetuloa!", "*" print "*" * 15
Ohjelman tulostus on seuraava:
*************** * Tervetuloa! * ***************
Tässä "*" * 15 on lyhennysmerkintä, joka tarkoittaa 15 tähtimerkkiä. Vastaavasti "abc" * 4 olisi merkkijono "abcabcabcabc".
Samalla tavalla voi toteuttaa ohjelman, jossa kaikki tekstit ovat laatikoissa:
# -*- coding: latin-1 -*-
print "*" * 15
print "*", "Tervetuloa!", "*"
print "*" * 15
print "*" * 20
print "*", "Anna tunnussana:", "*"
print "*" * 20
sana = raw_input()
if sana == "python":
print "*" * 11
print "*", "Oikein!", "*"
print "*" * 11
else:
print "*" * 11
print "*", "Väärin!", "*"
print "*" * 11Ohjelman tulostus voi olla seuraava:
*************** * Tervetuloa! * *************** ******************** * Anna tunnussana: * ******************** python *********** * Oikein! * ***********
Ohjelma toimii kyllä halutulla tavalla, mutta sen koodissa on turhaa toistoa, koska laatikon tulostavat komennot on kopioitu moneen kohtaan. Seuraavaksi nähdään, kuinka koodin rakennetta voi parantaa funktion avulla.
Seuraavassa ohjelmassa on funktio laatikko, joka tulostaa halutun tekstin laatikkoon. Ohjelman toiminta vastaa edellistä ohjelmaa, mutta koodin rakenne on huomattavasti selkeämpi.
# -*- coding: latin-1 -*-
def laatikko(teksti):
print "*" * (len(teksti) + 4)
print "*", teksti, "*"
print "*" * (len(teksti) + 4)
laatikko("Tervetuloa!")
laatikko("Anna tunnussana:")
sana = raw_input()
if sana == "python":
laatikko("Oikein!")
else:
laatikko("Väärin!")Funktion alussa on sana def, jonka jälkeen tulee funktion nimi laatikko. Sitten suluissa ovat funktion parametrit. Tässä funktiolla on yksi parametri teksti, joka tarkoittaa tekstiä, joka funktion täytyy tulostaa laatikkoon.
Funktio laatikko yleistää tekstin tulostuksen laatikkoon. Funktiolle voi antaa parametrina minkä tahansa tekstin ja funktio osaa tulostaa sen ympärille oikean määrän tähtimerkkejä. Merkintä "*" * (len(teksti) + 4) tarkoittaa, että tähtimerkkejä on neljä enemmän kuin tekstin pituus.
Seuraavassa ohjelmassa myös laatikon reunamerkki on funktion parametri:
# -*- coding: latin-1 -*-
def laatikko(teksti, reuna):
print reuna * (len(teksti) + 4)
print reuna, teksti, reuna
print reuna * (len(teksti) + 4)
laatikko("Tervetuloa!", "*")
laatikko("Anna tunnussana:", "?")
sana = raw_input()
if sana == "python":
laatikko("Oikein!", "!")
else:
laatikko("Väärin!", "!")Ohjelman tulostus voi olla seuraava:
*************** * Tervetuloa! * *************** ???????????????????? ? Anna tunnussana: ? ???????????????????? python !!!!!!!!!!! ! Oikein! ! !!!!!!!!!!!
Nyt funktiolla on kaksi parametria: parametri teksti on tulostettava teksti ja parametri reuna on merkki, jolla teksti täytyy ympäröidä.
Funktio palauttaa usein arvon ohjelman kohtaan, jossa funktiota kutsutaan. Näin toimii esimerkiksi funktio len, joka palauttaa sille annetun merkkijonon pituuden. Funktiossa komento return poistuu funktiosta ja palauttaa arvon.
Seuraavassa ohjelmassa on funktio kaanna, joka kääntää merkkijonon toisinpäin. Ohjelma kysyy käyttäjältä sanoja ja kääntää niitä toisinpäin.
# -*- coding: latin-1 -*-
def kaanna(mjono):
uusi = ""
for merkki in mjono:
uusi = merkki + uusi
return uusi
while True:
sana = raw_input("Anna sana: ")
if sana == "":
break
print "Toisinpäin: " + kaanna(sana)Ohjelman tulostus voi olla seuraava:
Anna sana: kirja Toisinpäin: ajrik Anna sana: valinta Toisinpäin: atnilav Anna sana: puro Toisinpäin: orup Anna sana:
Ohjelma kutsuu silmukassa funktiota kaanna parametrina käännettävä sana. Funktio muodostaa käännetyn sanan ja palauttaa sen komennolla return. Sitten käännetty sana liittyy tulostettavan merkkijonon osaksi.
Funktion kaanna avulla voi myös tarkistaa, onko sana palindromi eli onko se sama alusta loppuun ja lopusta alkuun luettuna. Tehdään sitä varten uusi funktio palindromi:
def palindromi(sana):
return sana == kaanna(sana)Tämä funktio palauttaa totuusarvon (True tai False) sen mukaan, onko sille annettu sana palindromi vai ei. Funktio palindromi kutsuu funktiota kaanna, koska se haluaa verrata sanaa toisinpäin käännettyyn sanaan. Jos sana on palindromi, se on sama käännettynä.
Seuraava ohjelma kertoo, ovatko käyttäjän antamat sanat palindromeja:
# -*- coding: latin-1 -*-
def kaanna(teksti):
uusi = ""
for merkki in teksti:
uusi = merkki + uusi
return uusi
def palindromi(teksti):
return teksti == kaanna(teksti)
while True:
sana = raw_input("Anna sana: ")
if sana == "":
break
if palindromi(sana):
print "Sana on palindromi!"
else:
print "Sana ei ole palindromi!"Ohjelman tulostus voi olla seuraava:
Anna sana: enne Sana on palindromi! Anna sana: kaivo Sana ei ole palindromi! Anna sana: syksy Sana ei ole palindromi! Anna sana: autioitua Sana on palindromi! Anna sana:
Kun käyttäjä kirjoittaa sanan, tapahtuu seuraavaa:
palindromi.palindromi kutsuu funktiota kaanna.kaanna palauttaa funktiolle palindromi käännetyn sanan.palindromi palauttaa pääohjelmalle arvon True, jos sana on palindromi, ja arvon False, jos sana ei ole palindromi.Alkuluku on positiivinen kokonaisluku, joka on jaollinen vain luvulla 1 ja itsellään. Lisäksi on sovittu, että luku 1 ei ole alkuluku. Seuraava ohjelma etsii kaikki alkulukut, jotka ovat pienempiä kuin 50.
# -*- coding: latin-1 -*-
def alkuluku(luku):
if luku < 2:
return False
for jakaja in range(2, luku):
if luku % jakaja == 0:
return False
return True
for luku in range(50):
if alkuluku(luku):
print luku,Ohjelman tulostus on seuraava:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
Funktio alkuluku käsittelee luvun seuraavasti:
False.False.True.Tässä range(2, luku) on lista, jonka ensimmäinen luku on 2 ja viimeinen luku on yksi pienempi kuin luku. Esimerkiksi range(2, 7) on lista [2, 3, 4, 5, 6]. Luku 7 ei ole jaollinen millään näistä luvuista, joten luku 7 on alkuluku.
Seuraava ohjelma näyttää tilaston listan aineistosta:
# -*- coding: latin-1 -*-
def tilasto(luvut):
if len(luvut) == 0:
print "Tyhjä aineisto!"
return
for luku in luvut:
print "*" * luku, luku
print "Keskiarvo:", float(sum(luvut)) / len(luvut)
tilasto([5, 3, 10, 8, 4, 4, 9, 3])Ohjelman tulostus on seuraava:
***** 5 *** 3 ********** 10 ******** 8 **** 4 **** 4 ********* 9 *** 3 Keskiarvo: 5.75
Funktion tilasto parametri on lista lukuja. Jos lista on tyhjä, funktio tulostaa virheviestin ja päättyy heti. Tässä funktio ei palauta arvoa, minkä vuoksi komennon return ainoa tarkoitus on poistua funktiosta.
Funktio käy läpi listan luvut ja tulostaa niitä vastaavat palkit. Lopuksi funktio laskee lukujen keskiarvon jakamalla lukujen summan niiden määrällä. Lukujen summa on muutettu liukuluvuksi, jotta jakolaskun lopputulos on liukuluku.
Funktion sisäiset muuttujat eivät vaikuta pääohjelman ja muiden funktioiden muuttujiin. Seuraavassa ohjelmassa sekä pääohjelmassa että funktiossa on muuttuja nimi, mutta muuttujat ovat erillisiä. Vaikka funktion muuttuja nimi saa arvon "Uolevi", pääohjelman muuttujan nimi arvo on edelleen "Henrikki".
# -*- coding: latin-1 -*-
def muutos():
nimi = "Uolevi"
nimi = "Henrikki"
muutos()
print nimi # tulostaa "Henrikki"Sanan global avulla pääohjelman ja funktion muuttujat voi yhdistää. Seuraavassa ohjelmassa muuttuja nimi on yhteinen, jolloin funktion suorituksen jälkeen myös pääohjelmassa muuttujan nimi arvo on "Uolevi".
# -*- coding: latin-1 -*-
def muutos():
global nimi
nimi = "Uolevi"
nimi = "Henrikki"
muutos()
print nimi # tulostaa "Uolevi"Olen saanut selville että tämän oppaan koodeista voi yhdistää "Ritari Henrikki"-pelin joka sijoittuu keskiajalle.
Huomio! Kommentoi tässä ainoastaan tämän oppaan hyviä ja huonoja puolia. Älä kirjoita muita kysymyksiä tähän. Jos koodisi ei toimi tai tarvitset muuten vain apua ohjelmoinnissa, lähetä viesti keskusteluun.