135
 T–106.1208 Ohjelmoinnin perusteet Y (Python) Opetusmoniste kevät 2013 Kerttu Pollari-Malmi ©Kerttu Pollari-Malmi

ohjelmoinnin perusteet

  • Upload
    esa

  • View
    105

  • Download
    1

Embed Size (px)

DESCRIPTION

ohjelmoinnin perusteet, python

Citation preview

  • T106.1208Ohjelmoinnin perusteet Y (Python)

    Opetusmoniste kevt 2013

    Kerttu Pollari-Malmi

    Kerttu Pollari-Malmi

  • Sislt

    1 Tietokoneista ja ohjelmista 1

    1.1 Lyhyesti tietokoneen rakenteesta . . . . . . . . . . . . . . . . . . . . 1

    1.2 Mik on tietokoneohjelma? . . . . . . . . . . . . . . . . . . . . . . . 1

    1.3 Mihin teekkari tai diplomi-insinri tarvitsee ohjelmointia? . . . . . 3

    2 Python-ohjelmoinnin alkeita 5

    2.1 Yksittisten kskyjen antaminen Python-tulkille . . . . . . . . . . . 5

    2.2 Ohjelman kirjoittaminen tiedostoon . . . . . . . . . . . . . . . . . . 6

    2.3 Ohjelman kirjoittaminen ja ajaminen Eclipsell . . . . . . . . . . . . 6

    2.4 Muuttujat, sijoitusksky ja tiedon lukeminen kyttjlt . . . . . . . 8

    2.5 Erilaisia tyyppej . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

    2.6 Laskutoimituksia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

    2.7 Lis sijoituskskyst . . . . . . . . . . . . . . . . . . . . . . . . . . 11

    2.8 Ohjelman jako funktioihin ja pohjelma . . . . . . . . . . . . . . . . 12

    2.9 Joitakin esimerkkiohjelmia . . . . . . . . . . . . . . . . . . . . . . . . 14

    2.9.1 Huoneen pinta-ala . . . . . . . . . . . . . . . . . . . . . . . . 14

    2.9.2 Puhelun hinta . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

    2.9.3 Aikamuunnoksia . . . . . . . . . . . . . . . . . . . . . . . . . 16

    2.10 Kommentit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

    3 Kontrollirakenteet: valinta ja toisto 19

    3.1 Valintaksky if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

    3.1.1 Loogiset operaattorit . . . . . . . . . . . . . . . . . . . . . . . 22

    3.1.2 Siskkisi if-kskyj . . . . . . . . . . . . . . . . . . . . . . . 23

    3.2 Toistoksky . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

    i

  • SISLT ii

    3.2.1 Toistoksky while . . . . . . . . . . . . . . . . . . . . . . . . 26

    3.2.2 Esimerkki: valintaksky toistokskyn sisll . . . . . . . . . . 30

    3.2.3 Iteraatioesimerkki . . . . . . . . . . . . . . . . . . . . . . . . 31

    3.2.4 Toistoksky for ja range-funktio . . . . . . . . . . . . . . . . 33

    3.2.5 Tulostuksen muotoilusta . . . . . . . . . . . . . . . . . . . . . 35

    3.2.6 Asuntolainaesimerkki . . . . . . . . . . . . . . . . . . . . . . 38

    4 Funktiot 41

    4.1 Yksinkertaisia esimerkkej . . . . . . . . . . . . . . . . . . . . . . . . 41

    4.2 Parametrit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

    4.3 Arvon palauttavat funktiot . . . . . . . . . . . . . . . . . . . . . . . 45

    4.3.1 Siskkiset funktiokutsut . . . . . . . . . . . . . . . . . . . . 48

    4.3.2 Totuusarvon palauttavat funktiot ja niiden paluuarvon kytt 49

    5 Listat, merkkijonot ja sanakirja 52

    5.1 Lista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

    5.1.1 Lista funktion parametrina ja funktion palauttamana arvona 57

    5.1.2 Haku listasta . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

    5.1.3 Muita listan ksittelyyn tarkoitettuja funktioita ja metodeita 66

    5.2 Merkkijono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

    5.3 Monikko . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

    5.4 Sanakirja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

    5.5 Arvot ja viittaukset . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

    5.5.1 Muuttujat ja niiden arvot . . . . . . . . . . . . . . . . . . . . 79

    5.5.2 Muuttuvat tyypit . . . . . . . . . . . . . . . . . . . . . . . . . 81

    5.5.3 Parametrin arvon muuttaminen funktion sisll . . . . . . . . 82

    6 Poikkeukset ja tiedostojen ksittely 87

    6.1 Poikkeukset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

    6.2 Tekstitiedostojen ksittely . . . . . . . . . . . . . . . . . . . . . . . . 90

    6.2.1 Lukeminen tekstitiedostosta . . . . . . . . . . . . . . . . . . . 90

    6.2.2 Kirjoittaminen tiedostoon . . . . . . . . . . . . . . . . . . . . 96

    6.2.3 Tiedostojen kytst . . . . . . . . . . . . . . . . . . . . . . . 100

  • SISLT iii

    7 Luokat ja oliot 101

    7.1 Mit oliot ovat? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

    7.2 Luokan mrittely ja olioiden ksittely . . . . . . . . . . . . . . . . . 102

    7.3 Toinen esimerkki . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

    7.4 Olio metodin parametrina: luokka Tasovektori . . . . . . . . . . . . 114

    7.5 Kenttien yksityisyydest . . . . . . . . . . . . . . . . . . . . . . . . . 118

    7.6 Lista luokan kenttn . . . . . . . . . . . . . . . . . . . . . . . . . . 122

    7.7 Listan alkiona olioita . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

  • Luku 1

    Tietokoneista ja ohjelmista

    1.1 Lyhyesti tietokoneen rakenteesta

    Tietokoneen perusosia ovat prosessori eli suoritin, keskusmuisti, syttlaitteet ja tu-lostuslaiteet. Prosessori varsinaisesti suorittaa tietokoneohjelmat. Se pystyy esimer-kiksi laskemaan kaksi lukua yhteen, tutkimaan onko jokin luku suurempi kuin nolla,hakemaan ksiteltvi lukuja keskusmuistista jne.

    Keskusmuisti on se tietokoneen osa, jossa sijaitsee parhaillaan suoritettava ohjelmaja sen ksittelem data, esimerkiksi ne luvut, joille ohjelmassa pit tehd lasku-toimituksia. Keskusmuisti koostuu perkkisist muistipaikoista, joista jokaisella onoma tunnus, osoite. Yhteen muistipaikkaan voidaan tallentaa yksittinen merkki taiosa yhdest luvusta. Kun tietokone sammutetaan, sen keskusmuistissa oleva tietokatoaa.

    Syttlaitteella kyttj voi antaa kskyj ja dataa tietokoneelle. Tyypillisi syt-tlaitteita ovat esimerkiksi nppimist ja hiiri. Tulostuslaitteilla, esimerkiksi nyt-tptteell ja tulostimella taas tietokone antaa tietoa kyttjlle.

    Keskusmuistin lisksi tietokoneeseen on yleens liitetty ulkoista muistia, esimerkiksikovalevy ja vliaikaisesti muistitikku. Tllainen ulkoinen muisti voi toimia tietoko-neessa sek sytt- ett tulostuslaitteena.

    1.2 Mik on tietokoneohjelma?

    Tietokoneen toimintaa ohjataan tietokoneohjelman avulla. Ohjelma on jono yksin-kertaisia kskyj, joita tietokoneen prosessori suorittaa jrjestyksess yksi kerral-laan. Tilannetta voi verrata siihen, ett kokki tekee ruokaa keittokirjan ohjeen avul-la. Kokki lukee resepti ja suorittaa siin olevia kskyj jrjestyksess. Kun keit-tokirjassa on kskyj "vatkaa munat ja sokeri vaahdoksi", "lis jauhot munasoke-rivaahtoon", niin tietokoneohjelmassa voi olla esimerkiksi seuraavanlaisia kskyj:"pyyd kyttjlt luku ja lue se", "vhenn luvusta 32", "kerro erotus viidell", "jaatulos yhdeksll" ja "tulosta kuvaruudulle nin saatu lopputulos".

    Tietokoneohjelmalla ja keittokirjan reseptill on mys eroja. Reseptiss osa kskyis-t voi olla epmrisi, esimerkiksi "lis suolaa maun mukaan". Tietokoneohjel-

    1

  • LUKU 1. TIETOKONEISTA JA OHJELMISTA 2

    massa kaikkien kskyjen tytyy olla tsmllisi ja tysin yksiselitteisi. Reseptinkskyj suoritetaan yleens siin jrjestyksess kuin ne on ohjeessa annettu. Tieto-koneohjelmassa on usein kskyj, jotka aiheuttavat sen, ett ohjelman suorituksessahyptn kokonaan toiseen paikkaan ohjelmassa.

    Tietokoneen ymmrtmt kskyt ovat hyvin yksinkertaisia, kuten "Laske kaksi lukuayhteen", "Hypp ohjelmassa kohtaan X". Tietokoneen tehokkuus ja monikyttisyysperustuu siihen, ett tietokone pystyy suorittamaan nit kskyj todella nopeasti.

    Lisksi kskyt pit esitt tietokoneelle bittijonoina eli erilaisina ykksten ja nollienyhdistelmin. Tt kutsutaan konekieleksi. Ensimmisi rakennettuja tietokoneitaohjelmoitiinkin niin, ett koneessa olevien kytkimien avulla koneelle annettiin yk-ksten ja nollien jonoja, jotka muodostivat kskyj. Tllainen ohjelmointi oli luon-nollisesti hyvin hidasta ja virhealtista. Jos yksikin kytkin oli vrss asennossa,koko ohjelman suoritus meni sekaisin.

    Ohjelmoinnin helpottamiseksi kehitettiin symbolinen konekieli, Assembler. Siinkskyj ei esitet en bittijonoina, vaan jokaista ksky varten on sovittu mrt-ty sana, esimerkiksi yhteenlaskuksky on yleens add ja vhennyslaskuksky sub.Lisksi kskyt sisltvt tiedon siit, miss ovat ne luvut, joille operaatio tehdn.Tietokone ei suoraan ymmrr symbolisen konekielen kskyj, vaan jotta symbolisel-la konekielell kirjoitettu tietokoneohjelma voitaisiin suorittaa, pit ensin muuttaasymbolisen konekielen kskyt tietokoneen ymmrtmiksi bittijonoiksi. Tt muun-nosta ei tarvitsee kuitenkaan suorittaa ksin, vaan voidaan kirjoittaa tietokoneoh-jelma, joka suorittaa muunnoksen. Jokaista symbolisen konekielen ksky vastaasuoraan yksi mrtty bittijono, joten muunnoksen suorittaminen on hyvin suora-viivaista.

    Symbolisenkin konekielen ongelmana on kuitenkin se, ett ohjelmoija joutuu sitkyttessn ajattelemaan asioita huomattavasti yksityiskohtaisemmin kuin mikon tarkoituksenmukaista. Ohjelmoijan pit esimerkiksi koko ajan olla selvill sii-t, miss kohdassa tietokoneen muistissa ksiteltvt luvut tsmllisesti sijaitsevat.Jos haluataan laskea kaksi lukua yhteen, vaatii tm usein monta konekielen ks-ky, kun ksiteltvi lukuja on ensin siirrettv keskusmuistista prosessorin sislloleviin muistipaikkoihin. Niden yksityiskohtien ajatteleminen tekee ohjelmoinnintylksi ja lis mys virhemahdollisuuksia. Lisksi jokaiselle prosessorityypille onoma konekieli. Yhdelle tietokoneelle symbolisella konekielell kirjoitettu ohjelma eitoimi toisentyyppisess tietokoneessa.

    Symbolisen konekielen ongelmien ratkaisemiseksi ruvettiin vhitellen kehittmnlausekieli. Lausekielisiss ohjelmissa monta perkkist konekielen ksky on kor-vattu yhdell lausekielen kskyll. Kskyt on suunniteltu niin, ett ne vastaisivatsellaisia loogisia kokonaisuuksia, joita ohjelmoija ajattelee. Python on yksi lausekieli.Muita lausekieli ovat esimerkiksi Cobol, Fortran, Pascal, C, C++ ja Java.

    Tietokone ei kuitenkaan ymmrr lausekielist ohjelmaa sellaisenaan, vaan lause-kielinen ohjelma on muutettava konekieliseksi, jotta se voitaisiin suorittaa. Thntarkoitukseen kytetn jlleen toista ohjelmaa. Tarkoitukseen kytettvt ohjelmatvoidaan jakaa kahteen luokkaan, kntjiin ja tulkkeihin.

    Kntj ottaa koko lausekielisen ohjelman, muuttaa sen konekielelle ja tallentaakonekielisen ohjelman tiedostoon. Tmn jlkeen konekielinen ohjelma voidaan ajaamielivaltaisen monta kertaa ilman, ett ohjelmaa tarvitsee knt uudelleen.

  • LUKU 1. TIETOKONEISTA JA OHJELMISTA 3

    Tulkki ky lpi lausekielist ohjelmaa ksky kerrallaan, muuttaa kskyn konekielelleja suorittaa konekielisen kskyn tai kskyt. Tmn jlkeen tulkki siirtyy lausekielisenohjelman seuraavaan kskyyn. Konekielisi kskyj ei tallenneta minnekn, vaanjos ohjelma halutaan suorittaa uudelleen, pit se mys tulkita kokonaan uudelleen.Python-kielisen ohjelman suorittamiseen kytetn tulkkia.

    Lausekielten etu symboliseen konekieleen verrattuna on se, ett ohjelmointi niill onnopeampaa ja vhemmn virhealtista. Lisksi ohjelmointi ei en riipu siit tieto-koneesta, jolla ohjelma aiotaan suorittaa. Lausekielell kirjoitettu ohjelma voidaanajaa mill tietokoneella tahansa, kunhan tlle tietokoneelle on olemassa kntj taitulkki, joka muuttaa kyseisell lausekielell kirjoitetun ohjelman konekieliseksi.

    Python-ohjelmointikielest on eri versioita sen mukaan, kuinka uutta Python-tulkkiakytetn. Tll kurssilla kytetn Python-versiota 3.2, koska tm versio on tllhetkell asennettu Aalto IT:n Linux-tietokoneisiin. Kotikoneeseen voi hyvin asentaamys version 3.3, sill niden kahden version vlill ei ole sellaisia eroja, joilla olisimerkityst tll kurssilla. Sen sijaan versiossa 2.7 ja sit vanhemmissa versioissa onolennaisia muutoksia uudempiin verrattuna, eik niden versioiden kytt ole tllkurssilla en mahdollista.

    1.3 Mihin teekkari tai diplomi-insinri tarvitsee ohjel-mointia?

    Suurin osa tietokoneen kytst on valmiiden ohjelmien (esimerkiksi tekstinksitte-ly, taulukkolaskenta, www-selain) kytt. Nit ohjelmia kirjoittavat yleens oh-jelmointialan ammattilaiset, eik muun alan diplomi-insinrin tarvitse tehd niititse. Toisenkin alan diplomi-insinrille ja teekkarille tulee kuitenkin vastaan tilan-teita, joissa on hydyllist osata kirjoittaa oma tietokoneohjelma.

    Yksi tyypillinen esimerkki on tilanne, jossa tarvitaan pient laskentasovellusta. Pi-tisi lukea lhttiedot tiedostosta, tehd niille joitakin laskutoimituksia, jotka saat-tavat sislt esimerkiksi optimointia tai iterointia, ja tulostaa tulokset kuvaruu-dulle tai tiedostoon. Laskutoimituksia tarvitaan niin paljon, ett niiden tekeminentaskulaskimella tai taulukkolaskentaohjelmalla on liian tylst.

    Toinen esimerkki on tilanne, jossa pitisi liitt mittalaite tai vastaava tietokonee-seen. Usein tllaisen laitteen mukana tulee joukko aliohjelmia, joiden avulla voidaanesimerkiksi kynnist laite, lopettaa sen toiminta ja muuttaa laitteen asetuksia.Laitteen kyttjn on kuitenkin kirjoitettava itse pieni ohjelma, joka kynnistlaitteen mukana tulleet aliohjelmat halutussa jrjestyksess.

    Mys erilaisia taulukko- ja matriisilaskentaohjelmia kytettess ohjelmointitaidostaon paljon hyty.

    Ohjelmointitaito auttaa mys valmiiden kaupallisten ohjelmien kytn oppimisessaja niiden toiminnan ymmrtmisess. Kun on ksitys niist periaatteista, jotka ovatohjelmoinnin taustalla, on paljon helpompi ymmrt, miksi valmis ohjelma toimiiniin kuin se toimii.

    Jos on kiinnostunut opiskelelmaan ohjelmointia enemmn, niin tyelmss on pal-jon paikkoja sellaisille henkilille, jotka hallitsevat hyvin jonkin insinrialan ja osaa-vat lisksi ohjelmoida hyvin. Tllaiset henkilt kirjoittavat yleens omaan alaansa

  • LUKU 1. TIETOKONEISTA JA OHJELMISTA 4

    liittyvi ohjelmia. Tllaisiin tytehtviin ei tosin tll kurssilla opetettava ohjelmoin-titaito riit, vaan silloin ohjelmointia on opiskeltava selvsti enemmn. Sen sijaantss luvussa aiemmin mainitut tavoitteet ovat saavutettavissa jo tmn kurssinjlkeen.

  • Luku 2

    Python-ohjelmoinnin alkeita

    2.1 Yksittisten kskyjen antaminen Python-tulkille

    Python on tulkattava kieli. Python-tulkki ottaa suoritettavasta ohjelmasta yhdenkskyn kerrallaan, muuttaa sen konekielelle ja suorittaa kskyn saman tien. T-m aiheuttaa sen, ett Python-tulkilla ei tarvitse olla ohjelman loppua tiedos-saan viel silloin, kun se suorittaa ohjelman alkua. Niinp Python-tulkin toimin-taa voi aluksi kokeilla siten, ett antaa tulkille kskyn kerrallaan. Aalto-yliopistonLinux-tietokoneissa Python-tulkki voidaan kynnist kirjoittamalla komentoikku-nassa ksky python3.2. Kuvaruudulle ilmestyy kehote >>>, jonka pern kyttjvoi kirjoittaa haluamansa kskyn. Tulkki suorittaa kskyn saman tien ja tulostaasen tuloksen kuvaruudulle. Alla on esimerkki istunnosta, jossa kyttj on antanuttulkille kaksi ksky:

    > python3.2Python 3.2.3 (default, Oct 19 2012, 20:10:41)[GCC 4.6.3] on linux2Type "help", "copyright", "credits" or "license" for more information.>>> 5 + 712>>> print("kaunis ilma")kaunis ilma>>>

    Ensimminen ksky 5 + 7 tarkoittaa sit, ett kyttj pyyt Python-tulkkia las-kemaan annetun yhteenlaskun. Tulkki laskeekin sen ja seuraavalla rivill antaa tu-loksen. Jlkimminen ksky print("kaunis ilma") taas pyyt tulkkia tulosta-maan tekstin "kaunis ilma". Tss kskyss sana print merkitsee pyynt tulostaajotain ja tulostettava teksti on annettu sen jlkeen sulkujen sisll. Koska tulostet-tava teksti halutaan tulostaa sellaisenaan, se on annettu lainausmerkeiss (muussatapauksessa tulkki lhtisi tutkimaan, liittyyk sanoihin kaunis ja ilma jokin arvo, jo-ka pitisi ottaa huomioon). Kuten nhdn, tulkki on seuraavalla rivill tulostanutpyydetyn tekstin.

    Tulkin toiminta lopetetaan antamalla ksky exit() tai vaihtoehtoisesti tiedostonloppu -merkki, joka on Unix/Linux -kyttjrjestelmss Ctrl-D.

    5

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 6

    Huomautus: Python-tulkin kynnistvn kskyn tarkka muoto vaihtelee eri ymp-ristiss. Usein se on vain pelkk python. Aalto IT:n Linux-koneissa tm kskykynnist kuitenkin vanhemman version Python-tulkista. Tll kurssilla kytett-v versio kynnistetn edell esitetyll kskyll python3.2.

    2.2 Ohjelman kirjoittaminen tiedostoon

    Kskyjen antaminen Python-tulkille yksitellen on ktev silloin, jos haluaa vain tut-kia yksittisten kskyjen toimintaa. Menetelmss on kuitenkin se huono puoli, ettsuoritetut kskyt eivt j minnekn talteen. Jos samat kskyt haluaa suorittaauudelleen, pit ne kirjoittaa joka kerta yksi kerrallaan. Jos sama ohjelma halutaansuorittaa monta kertaa, kannattaa ohjelmaan kuuluvat kskyt kirjoittaa tiedostoon.Kun ohjelma on tallennettu tiedostoon, voidaan se suorittaa kuinka monta kertaahyvns.

    Esimerkiksi ohjelma, joka tulostaa kuvaruudulle "kaunis ilma", voidaan tehd seu-raavasti. Kynnistetn mik tahansa tekstieditori (esimerkiksi Emacs tai Notepad),jonka avulla voidaan helposti tallentaa pelkk teksti. Tavalliset tekstinksittely-ohjelmat, esimerkiksi Word, eivt ole hyvi thn tarkoitukseen, koska ne tallenta-vat tiedostoon itse tekstin lisksi tekstin muotoiluun liittyv tietoa, joka sekoittaaPython-tulkin. Kirjoitetaan tiedostoon rivi

    print("kaunis ilma")

    Jos kirjoitettava ohjelma sislt useamman kuin yhden rivin, ne kirjoitetaan kaikkithn samaan tiedostoon. Tmn jlkeen tiedosto pit tallentaa. Siin yhteydesstiedostolle annetaan nimi. Tiedoston nimess pit olla pte ".py", josta tunniste-taan, ett tiedosto sislt Python-ohjelman. Jos edellinen ohjelma on tallennettutiedostoon tulostuskokeilu.py, voi sen ohjelman suorittaa kskyll

    python3.2 tulostuskokeilu.py

    Ohjelman suoritus nytt silloin seuraavalta:

    > python3.2 tulostuskokeilu.pykaunis ilma

    Huomautus: Jlleen ohjelman suorituksessa tarvittava ksky voi olla pelkstnpython tulostuskokeilu.py jossain toisessa ympristss kuin Aalto IT:n Linux-koneessa.

    2.3 Ohjelman kirjoittaminen ja ajaminen Eclipsell

    Edellisess esimerkiss neuvottiin, miten Python-ohjelma voidaan kirjoittaa mil-l tahansa tekstieditorilla ja ajaa sitten kyttjrjestelmn puolella annettaval-la python3.2-kskyll. Toinen vaihtoehto on kytt ohjelman kirjoittamiseen in-tegroitua kehitysymprist (engl. Integrated Development Environment, IDE). Se

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 7

    on tykalu, joka tyypillisesti sislt vlineet sek ohjelmatiedoston kirjoittamiseenett ohjelman ajamiseen sek muita apuvlineit (esimerkiksi debuggerin, joka avul-la voi helposti etsi ohjelmasta virheit). Tll kurssilla ohjelmien kirjoittaminenkytetn Eclipse-tykalua. Tss kappaleessa selitetn, miten ohjelma voidaankirjoittaa ja ajaa Eclipse-tykalun avulla. Tarkemmat ohjeet Eclipsen kyttn ontmn kurssin kotisivulla. Niinp tss opetusmonisteessa on esitetty vain lyhyestiperiaatteet, ja yksityiskohdat on syyt lukea kurssin kotisivulta.

    Jotta Eclipse voisi kytt Python-ohjelmointiin, pit siihen ensin ladata sopivalisosa, plugin. Tll kurssilla kytetn Pydev-nimist pluginia. Tarkemmat ohjeetPydevin asennukseen on kurssin kotisivulla.

    Kynnist Eclipse antamalla kyttjrjestelmn puolella komento eclipse tai graa-fisessa ympristss kaksoisklikkaamalla Eclipsen kuvaketta. Pienen odottelun jl-keen nkyviin tulee Eclipsen ikkuna.

    Eclipsess kaikki ohjelmat kuuluvat johonkin projektiin. Jos kirjoitettavalle ohjel-malle sopivaa projektia ei ole aikaisemmin luotu, pit se ensin luoda valitsemallaFile->New->Pydev Project. Eclipse kysyy projektin nime. Eclipse kysyy myskohdassa Grammar Version, mit Pythonin versiota kytetn. Valitse tss 3.0.

    Kun projekti on luotu, pit viel luoda tiedosto, johon ohjelma kirjoitetaan. Tl-laista tiedostoa kutsutaan moduuliksi. Se luodaan valitsemalla ensin projekti, jo-hon moduuli tulee, ja sen jlkeen valikosta File->New->Pydev Module. Eclipse ky-syy luotavan tiedoston (moduulin) nimen. Tss yhteydess olisi mys mahdollistamritell pakkaus, mihin moduuli tulee. Samaan projektiin kuuluvat moduulit voi-daan jakaa useisiin pakkauksiin. Tll kurssilla tehtvt ohjelmat ovat kuitenkinniin pieni, ett pakkausten kytt ei ole tarpeellista.

    Kun moduulin nimi on annettu ja painettu finish-painiketta, ikkunan keskiosaanilmestyy tila, johon ohjelman koodin voi kirjoittaa. Python-tulkki tutkii koodia sa-malla kuin ohjelmoija kirjoittaa sit ja ilmoittaa havaitsemistaan virheist punaisillamerkeill. Jos kursorin vie punaisen merkin kohdalle, tulkki antaa tarkemman ku-vauksen havaitsemastaan virheest. Aina ei kuitenkaan ole kysymys varsinaisestavirheest, vaan vain siit, ett kirjoitettava rivi tai ohjelma on viel keskenerinen,eik sen vuoksi sisll kaikkia tarpeellisia asioita. Tllin virhemerkint poistuu it-sestn ohjelman kirjoituksen edetess.

    Kun ohjelma on kirjoitettu valmiiksi, eik Eclipse lyd siit en virheit,ohjelman voi ensin tallentaa File->Save-kskyll ja sitten ajaa valitsemallaRun->Run as->Python Run. Ohjelman tulosteet tulevat nyt ohjelmakoodin sislt-vn ikkunan osan alla olevaan konsoliosaan.

    Eclipse tallentaa kaikki sill kirjoitetut ohjelmatiedostot moduulinnnimi.py-nimi-sin tavallisina teksitiedostoina hakemistoon tyhakemisto/projektinnimi/. NinEclipsell kirjoitettuja ohjelmia pystyy ajamaan mys ilman Eclipse miss tahansaympristss, jossa vain on Python-tulkki kytss. Nin yleens tehdnkin val-miille ohjelmalle. Eclipse on nimenomaan ohjelman kehitysvaiheeseen tarkoitettuapuvline.

    Edell siis moduulinnimi tarkoittaa ohjelmoijan tlle moduulille antamaa nime.Kun ohjelmoija kytt Eclipse ensimmist kertaa, Eclipse pyyt hnt kerto-maan tyhakemiston, jonka alle kaikki ohjelmatiedostot tallennetaan. Tst hake-mistossa on edell kytetty nime tyhakemisto.

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 8

    2.4 Muuttujat, sijoitusksky ja tiedon lukeminen kyt-tjlt

    Yleens tietokoneohjelmissa halutaan, ett ohjelma voi lukea jotain tietoa kytt-jlt ja kytt tt tietoa hyvkseen. Ajatellaan esimerkiksi ohjelmaa, joka pyy-t kyttjlt lmptilan fahrenheit-asteina ja tulostaa saman lmptilan celsius-asteina. Ohjelmassa tytyy tllin olla jokin tapa tallentaa kyttjn antamafahrenheit-arvo ja ksitell sit.

    Tllaiseen arvojen tallentamiseen voidaan kytt muuttujia. Jokaisella muuttujal-la on nimi ja muuttujalle voi antaa arvon. Muuttujan nimen avulla psee ksiksithn muuttujan arvoon myhemmin ohjelmassa. Muuttujalle voi antaa arvon si-joituskskyn avulla. Sijoituskskyss on vasemmalla sen muuttujan nimi, jolle arvohalutaan antaa, sitten sijoitusoperaattori =, ja oikealla muuttujalle annettava arvo.Esimerkiksi ksky

    fahrenheit = 78.5

    sijoittaa muuttujan fahrenheit arvoksi 78.5. Sijoitettavan arvon ei tarvitse ollasuoraan jokin vakioarvo, vaan sijoitusoperaattorin oikealla puolella voi olla jokinlauseke, jonka arvo lasketaan ensin. Tmn jlkeen laskettu arvo annetaan arvoksivasemmalla puolella olevalle muuttujalle, esimerkiksi ksky

    celsius = (fahrenheit - 32) * 5.0 / 9.0

    vhent muuttujan fahrenheit arvosta 32, kertoo nin saadun tuloksen 5.0:lla jajakaa sen 9.0:lla ja sijoittaa nin saadun tuloksen muuttujan celsius arvoksi.

    Ennen kuin lhdetn tutkimaan fahrenheit-celsius-muunnoksen tekev ohjelmaaja lmptilatiedon lukemista kyttjlt tarkemmin, tarkastellaan viel yksinkertai-sempaa ohjelmaa. Se pyyt kyttj antamaan nimens, lukee kyttjn antamannimen ja tulostaa sitten kyttjlle osoitetun tervehdyksen.

    Kyttjn sytett voidaan lukea kskyn input -avulla. Esimerkiksi ksky

    nimi = input("Kerro nimesi: ")

    tulostaa ensin kuvaruudulle tekstin "Kerro nimesi: ", lukee sitten kyttjn antamantekstin ja sijoittaa sen muuttujan nimi arvoksi. Kskyss on siis inputin jlkeentulevien sulkujen sisll se teksti, joka kyttjlle halutaan ensin tulostaa. Luettuarvo annetaan jonkin muuttujan arvoksi sijoituskskyn avulla.

    Seuraavaksi koko ohjelma, joka lukee kyttjn tekstin ja tulostaa tervetulotoivo-tuksen:

    nimi = input("Kerro nimesi: ")print("Hei,", nimi)print("Tervetuloa Python-kurssille!")

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 9

    Nimen lukemisen jlkeen ohjelmassa on siis kaksi tulostusksky. Ensimminen niis-t tulostaa tekstin "Hei," sellaisenaan ja sen jlkeen samalle riville muuttujan nimiarvon. Sana Hei on lainausmerkkien sisll, koska se halutaan tulostaa sellaisenaan.Sana nimi sen sijaan ei ole lainausmerkkien sisll, koska ohjelman ei haluta tulos-taa teksti nimi, vaan muuttujan nimi arvo. Jos samassa tulostuskskyss halutaantulostaa enemmn kuin yksi asia (esimerkkitapauksessa sek teksti ett muuttujannimi arvo), erotetaan tulostettavat asiat toisistaan pilkulla. Tulostettavien asioidenvlille listn tulostuksessa yksi vlilynti.

    Ohjelman viimeinen rivi tulostaa tekstin "Tervetuloa Python-kurssille!". (Niiden,jotka ovat aikaisemmin ohjelmoineet jollain toisella kielell kannattaa huomata, et-t Python-ohjelmissa muuttujia ei mritell toisin kuin esimerkiksi Java- tai C-ohjelmissa.)

    Kun ohjelma ajetaan, nytt sen tulostus seuraavalta:

    Kerro nimesi: MaijaHei, MaijaTervetuloa Python-kurssille!

    Fahrenheit-Celsius-muunnoksen laskeva ohjelma on vhn monimutkaisempi. Tmjohtuu siit, ett input-ksky vlitt kyttjlt lukemansa sytteen aina merk-kijonona eli tekstin, joka koostuu perkkisist merkeist (nit merkkej voi ollayksi, useampi tai jopa nolla). Lmptilamuunnoksessa tarvitaan kuitenkin yhteen-,kerto- ja jakolaskuja. Python-tulkki ei voi suorittaa nit laskutoimituksia merkki-jonoille, vaan laskutoimituksen operandin on oltava luku. Oletetaan, ett kyttjnantama merkkijono on tallennettu muuttujaan rivi. Merkkijonoa vastaava lukuvoidaan tllin antaa muuttujan fahrenheit arvoksi kskyll

    fahrenheit = float(rivi)

    Tss ksky float muuttaa sille sulkujen sisll annetun merkkijonon tai sulkujensisll annetun muuttujan arvona olevan merkkijonon vastaavaksi desimaaliluvuksi.Muutos onnistuu vain, jos merkkijono todella esitt jotain desimaalilukua. Seuraa-vaksi koko ohjelma:

    rivi = input("Anna lampotila fahrenheit-asteina: ")fahrenheit = float(rivi)celsius = (fahrenheit - 32) * 5.0 / 9.0print(fahrenheit, "F on", celsius, "C")

    Ohjelman suoritus voi nytt seuraavalta:

    Anna lampotila fahrenheit-asteina: 79.579.5 F on 26.3888888889 C

    Kuten esimerkkiajosta nhdn, celsius-lmptila esitetn turhan tarkasti. Luvussa3.2.5 kerrotaan, miten tulosta voi muotoilla siistimmksi.

    Jos kyttjn antamaa merkkijono ei vastaa mitn lukua, ohjelma kaatuu eli selopettaa toimintansa ja tulostaa jonkinlaisen virheilmoituksen. Alla esimerkki ohjel-man tllaisesta suorituksesta:

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 10

    Anna lampotila fahrenheit-asteina: ei mikaan lukuTraceback (most recent call last):

    File "/m/home/lampotilat1.py", line 2, in fahrenheit = float(rivi)

    ValueError: could not convert string to float: ei mikaan luku

    Virheilmoitus ei nyt kovin helppolukuiselta, mutta se kertoo, miss ohjelman koh-dassa virhe on sattunut, millainen virhe oli kysymyksess ja mik virheen aiheutti.

    Edellisess esimerkiss ei ole kytetty ohjelman tulostuksissa skandinaavisia aakko-sia , ja , vaan ne on korvattu a:lla ja o:lla. Tm ei ole mitenkn pakollista,vaan Python-ohjelmissa pystytn ksittelemn mys nit kirjaimia. Kytnnsstll kurssilla on kuitenkin havaittu, ett - ja -kirjainten kyttminen aiheuttaaopiskelijoille usein harmia kurssilla kytettvn automaattisen tarkastusjrjestelmnkytss, kun opiskelijat tekevt harjoitustehtvi omilla kotikoneillaan, mutta ei-vt osaa asettaa kytettvi merkkien koodaustapoja oikein. Koska nist asioistahuolehtiminen ei ole tll kurssilla keskeinen asia, on opiskelijoiden harjoitusteht-vien tekemisen helpottamiseksi tll kurssilla luovuttu skandinaavisten aakkostenkyttmisest ohjelman tulostuksista.

    2.5 Erilaisia tyyppej

    Monessa muussa ohjelmointikieless pit jo ennen muuttujan ensimmist kyttmritell muuttuja ja kertoa, mik muuttujan tyyppi on. Muuttujan tyyppi m-r, millaisen arvon muuttujalle voi antaa. Python-ohjelmissa asia ei ole nin, vaanmuuttuja otetaan kyttn ilman mrittely. Siit huolimatta muuttujalle sijoitet-tavalla arvolla on jokin tyyppi, joka mr esimerkiksi sen, millaisia operaatiotamuuttujalle voidaan suorittaa. Kaksi kokonaislukua voidaan jakaa keskenn, muttakahta merkkijonoa ei.

    Seuraavaksi esitelln yleisimmt yksinkertaisissa ohjelmissa esiintyvt tyypit.

    Merkkijonoja (englannniksi string) kytetn ksittelemn erilaisia tekstej, esi-merkiksi nimi. Merkkijonoille ei voi suorittaa aritmeettisia laskutoimituksia, muttamerkkijonosta voi esimerkiksi selvitt sen pituuden ja kaksi merkkijonoa voi liittperkkin yhteen. Merkkijonoille mahdollisista operaatioista kerrotaan enemmn lu-vussa 5. Merkkijonon tyyppi Pythonissa on str.

    Kokonaisluvut ovat lukuja, joissa ei ole desimaalipistett. Niiden arvon tyyppi onPythonissa int. Jos lukuarvossa on desimaalipiste, sen tyyppi ei ole int, vaan float.Tt tyyppi kytetn desimaalilukujen arvojen tallentamiseen. On kuitenkin huo-mattava, ett float-arvot eivt ole reaalilukuja matemaattisessa mieless. Arvontallentamiseen kytettviss oleva muistitila asettaa rajat sille, kuinka tarkasti desi-maalilukuja voidaan esitt ja mik on suurin tai pienin mahdollinen desimaaliluku.Kytnnss tm voi johtaa yllttviin pyristysvirheisiin ohjelman toiminnassa.Jos esimerkiksi lasketaan yhteen hyvin suuri ja hyvin pieni positiivinen desimaalilu-ku, ei pienempi luku vaikuta vlttmtt lopputulokseen lainkaan, koska summantarkkuus ei riit kattamaan pienemmn luvun vaikutusta.

    Desimaaliluku ksitetn float-tyyppiseksi, vaikka sen desimaaliosa olisikin 0. Ninesimerkiksi arvon 5 tyyppi on Python-tulkin mielest int, mutta arvon 5.0 tyyppi

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 11

    on float. Tll on merkityst, sill int- ja float-tyyppiset arvot tallennetaan tie-tokoneen muistissa erilaisissa muodoissa ja mys jotkin operaatiot toimivat eri laillakokonais- ja desimaaliluvuille.

    Lisksi Python-kieless on tyyppi bool, jota kytetn totuusarvojen esittmiseen.Arvona on voi tllin olla joko True (tosi) tai False (eptosi).

    2.6 Laskutoimituksia

    Python-kieless kokonais- ja desimaaliluvuille on kytettviss laskutoimituksia var-ten operaattorit +, -, *, /, // %, * ja **. Operaattori + tarkoittaa yhteenlaskua, -vhennyslaskua, * kertolaskua, ja ** potenssiin korotusta. Nm operaatiot toimivataivan niin kuin arkikokemuksen perusteella voisi olettaa. Poikkeusena on edellisessluvussa mainitut, mahdolliset pyristysvirheist johtuvat eptarkkuudet.

    Operaattorit / ja // suorittavat jakolaskun. Operaattori / toimii, kuten arkiko-kemuksen perusteella jakolaskun voisi olettaa toimivan pyristysvirheit lukuunot-tamatta. Esimerkiksi laskutoimituksen 5 / 3 tulos on 1.6666666666666667. Sensijaan kytettess operaattoria // kahden positiivisen kokonaisluvun vlill tulok-seksi tulee varsinaisen jakolaskun tuloksen kokonaisosa. Niinp esimerkiksi laskutoi-mituksen 5 // 3 tulos on 1. Tulosta laskettaessa ei suoriteta mitn pyristyksi,vaan jakolaskun tuloksen kokonaisosa otetaan tulokseksi sellaisenaan, tosin negatii-visilla tuloksilla otetaan tulosta pienempi kokonaisluku. Operaattori // katkaiseetuloksesta desimaalit pois mys silloin, kun jaettavana on desimaalilukuja. Tuloksentyyppi on kuitenkin tllin float eik int.

    Operaattori % on jakojnns. Esimerkiksi lausekkeen 19 % 4 arvo on 3. Operaattori** tarkoittaa potenssiin korotusta. Esimerkiksi lausekkeen 3 ** 4 arvo on 81 jalausekkeen 3.0 ** 4 arvo on 81.0.

    Niden operaatioiden lisksi voidaan Python-ohjelmissa ottaa kyttn valmiita mo-duuleita, jotka sisltvt paljon lis laskutoimituksia, esimerkiksi trigonometrisiafunktioita ja logaritmeja. Nist kerrotaan tarkemmin myhemmin.

    2.7 Lis sijoituskskyst

    Tarkastellaan vhn tarkemmin sijoitusksky. Sijoituskskyss on vasemmalla jon-kin muuttujan nimi, sitten =-merkki ja tmn oikealla puolella lauseke, esimerkiksi

    keskiarvo = (4.5 + 8.7) / 2

    Sijoitusksky suoritetaan aina niin, ett ensin lasketaan oikealla puolella olevanlausekkeen arvo ja saatu tulos sijoitetaan vasemmalla puolella olevan muuttujanarvoksi.

    Laskettavassa lausekkeessa voi esiinty muuttujien nimi. Tllin lausekkeen arvoalaskettaessa kytetn niden muuttujien arvoja, esimerkiksi

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 12

    fahrenheit = 100;celsius = (fahrenheit - 32) * 5.0 / 9.0

    Sijoituskskyn vasemmalla puolella olevalla muuttujalla voi olla arvo jo ennen sijoi-tusksky. Tllin vanha arvo hvi sijoitusksky suoritettaessa, esimerkiksi

    celsius = 25.0fahrenheit = 100celsius = (fahrenheit - 32) * 5.0 / 9.0

    Muuttujan celsius arvo on ennen viimeisen kskyn suorittamista 25.0, mutta sensuorittamisen jlkeen noin 37.7777777778.

    Muuttujan vanhaa arvoa voidaan kytt mys hyvksi saman muuttujan uuttaarvoa laskettaessa, esimerkiksi

    luku = 5luku = luku + 7

    Jlkimminen sijoitusksky suoritetaan seuraavasti: lasketaan ensin oikealla puolellaolevan lausekkeen arvo. Otetaan siis muuttujan luku arvo (5), listn siihen 7, jol-loin lausekkeen arvoksi saadaan 12. Saatu arvo sijoitetaan muuttujan luku uudeksiarvoksi. Muuttujan luku arvo on siis ennen kskyn suorittamista 5 ja kskyn suo-rittamisen jlkeen 12. Ksky voi tuntua aluksi hmvlt, mutta on muistettava,ett merkki = tarkoittaa todellakin sijoitusta, eik sill ole Python-kieless mitntekemist yhtsuuruuden kanssa.

    Sijoituskskyt, joissa muuttujan vanhaa arvoa kytetn hyvksi uutta arvoa las-kettaessa ovat niin yleisi, ett osalle niist on sovittu lyhennysmerkint. Sijoitus

    luku += 7

    tarkoittaa samaa kuin sijoitusksky

    luku = luku + 7

    Vastaavasti toimivat merkinnt -=, *= ja /=.

    2.8 Ohjelman jako funktioihin ja pohjelma

    Thn asti esitetyt esimerkkiohjelmat ovat olleet korkeintaan muutaman rivin mit-taisia. Kytnnn elmss tarvitaan kuitenkin usein ohjelmia, jotka sisltvt sato-ja, tuhansia ja jopa kymmeni tuhansia rivej. Jos tllin koko pitk ohjelma koos-tuisi vain yhdest osasta, joka sisltisi suoritettavat ohjelmarivit perkkin, olisiohjelman rakenteen ja toiminnan hahmottaminen hyvin vaikeaa. Ohjelman rakennet-ta selkiytetn sill, ett ohjelma jaetaan funktioihin. Yhteen funktioon kirjoitetaan

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 13

    muutamasta rivist muutamaan kymmeneen riviin ohjelmakoodia, joka tyypillisestisuorittaa jonkin tehtvn. Funktiolle annetaan sen tarkoitusta kuvaava nimi. Kunohjelmassa sitten halutaan suorittaa thn funktioon kuuluvat kskyt, kirjoitetaanohjelmaan rivi, joka kutsuu tt funktiota eli pyyt suorittamaan tmn funktion.

    Sen lisksi, ett ohjelman jakaminen funktioihin selkeytt ohjelmaa, niin se myssst tyt. Jos samanlainen ohjelman osa pit suorittaa monta kertaa, riittkirjoittaa thn osaan kuuluvat kskyt yhden kerran yhdeksi funktioksi. Tmnjlkeen riitt kirjoittaa yksi ksky, funktion kutsu, aina kun kyseinen osa halutaansuorittaa.

    Luvussa 4 kerrotaan tarkemmin, miten funktioita mritelln ja mit kaikkea muu-ta asiaan liittyy. Tss vaiheessa opetellaan kuitenkin yhden erityisen funktion, p-ohjelman kirjoittaminen ja kutsuminen.

    Tyypillisesti Python-ohjelmassa on yksi erityisasemassa oleva funktio, jota kutsu-taan pohjelmaksi. Tmn funktion nimeksi annetaan yleens main ja se on se osaohjelmasta, josta ohjelman suoritus aloitetaan. Kun ohjelma kynnistetn, suorite-taan pohjelmassa olevia kskyj jrjestyksess, kunnes jokin pohjelmassa olevaksky (esimerkiksi toisen funktion kutsu) aiheuttaa sen, ett siirrytn ohjelmassajohonkin muualle. Pohjelman mrittelyss kerrotaan, mit kskyj pohjelmas-sa on. Mrittely aloitetaan rivill

    def main():

    Sana def kertoo, ett ollaan mrittelemss funktiota, main on mriteltvn funk-tion nimi ja itse mrittely tulee kaksoispisteen jlkeen. Nimen jlkeen olevat sulutliittyvt siihen, ett mriteltville funktioille on mahdollista mritell mys para-metreja, joista kerrotaan tarkemmin luvussa 4.

    Tmn rivin jlkeen tulevat varsinaiset pohjelmaan kuuluvat kskyt. Jokainenpohjelmaan kuuluva rivi on sisennetty. Sisennysten avulla osoitetaan, mitk rivitkuuluvat pohjelman mrittelyyn. Ensimminen niden rivien jlkeen tuleva si-sentmtn rivi ei en kuulu pohjelmaan. Esimerkiksi jos aikaisemmin esitettyfahrenheit-celsius-muunnoksen tekev ohjelma kirjoitetaan pohjelmaksi, nyttse seuraavalta:

    def main():rivi = input("Anna lampotila fahrenheit-asteina: ")fahrenheit = float(rivi)celsius = (fahrenheit - 32) * 5.0 / 9.0print(fahrenheit, "F on", celsius, "C")

    Pelkk pohjelman mrittely ei saa kuitenkaan ohjelmaa viel tekemn mitn.Ohjelmassa pit mys kutsua pohjelmaa eli kirjoittaa ksky, joka saa aikaiseksisen, ett suoritetaan main-niminen funktio (pohjelma). Tm ksky on yksinker-taisesti seuraava:

    main()

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 14

    eli kutsuttavan funktion nimi ja sen perss sulut. Pohjelman kutsu voidaan kir-joittaa ohjelmatiedostossa pohjelman mrittelyn jlkeen. Kutsua sisltv riviei ole en sisennetty, koska pohjelman kutsu ei kuulu pohjelman mrittelyyn.

    Kokonaisuudessaan siis esimerkkiohjelman sisltvn tiedostoon kirjoitetaan seu-raavat rivit:

    def main():rivi = input("Anna lampotila fahrenheit-asteina: ")fahrenheit = float(rivi)celsius = (fahrenheit - 32) * 5.0 / 9.0print(fahrenheit, "F on", celsius, "C")

    main()

    2.9 Joitakin esimerkkiohjelmia

    2.9.1 Huoneen pinta-ala

    Seuraava ohjelma pyyt kyttjlt suorakulmion muotoisen huoneen pituuden jaleveyden. Se laskee ja tulostaa huoneen pinta-alan. Esimerkist nhdn, kuinkakyttjlt voidaan lukea samassa ohjelmassa useampi arvo. Kukin luettu arvo (senjlkeen, kun se on muutettu desimaaliluvuksi) tallennetaan omaan muuttujaansa.

    def main():rivi = input("Anna huoneen leveys metreina: ")leveys = float(rivi)rivi = input("Anna huoneen pituus metreina: ")pituus = float(rivi)pinta_ala = leveys * pituusprint("Huoneen pinta-ala on", pinta_ala, "neliometria")

    main()

    Alla on esimerkki ohjelman suorituksesta.

    Anna huoneen leveys metreina: 4.5Anna huoneen pituus metreina: 3.8Huoneen pinta-ala on 17.1 neliometria

    Thnastisissa esimerkkiohjelmissa on kytetty lyhyiss Python-ohjelmissa varsinyleist tapaa, jossa kyttjlle annettava kehote (pyynt) on samalla rivill kuinmille kyttj kirjoittaa oman sytteens (vastauksen ohjelman kysymykseen). Tl-l kurssilla tehtviss harjoitustehtviss tavan kytt aiheuttaa kuitenkin ongelmia,koska harjoitustehtvt automaattisesti tarkastava Goblin-jrjestelm tutkii ohjel-mien tulostetta rivi kerrallaan. Ohjelman tulostuksen ja kyttjn sytteen erot-taminen tarkistuksessa on jrjestelmlle ongelmallista, jos ohjelman tuloste ei olevlimerkkej myten juuri annetun mallin mukainen.

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 15

    Turhien ongelmien vlttmiseksi tll kurssilla kirjoitetaan sen vuoksi palautetta-vat harjoitustehtvt niin, ett ohjelman tulostukset ptetn aina rivinvaihtoonja kyttj kirjoittaa mahdollisen sytteens vasta seuraavalle riville. Kskyn inputsulkujen sisll olevan tulostettavan merkkijonon saa pttymn rivinvaihtoon sil-l, ett lis merkkijonon loppuun erikoismerkin \n. Tm merkki siis kirjoitetaanpainamalla nppimistll ensin nppint \ ja nppint n, mutta merkkijonos-sa yhdistelm ksitetn yhdeksi merkiksi, joka aiheuttaa rivinvaihdon merkkijonoatulostettaessa. Ksky print lis itse rivinvaihdon tulostuksen jlkeen, joten print-ksky kytettess rivinvaihtoa ei tarvitse list.

    Alla pinta-alan laskeva ohjelma kirjoitettuna uudelleen niin, ett kaikki ohjelmantulosteet pttyvt rivinvaihtoon ja kyttj syte tulee omalle rivilleen.

    def main():rivi = input("Anna huoneen leveys metreina.\n")leveys = float(rivi)rivi = input("Anna huoneen pituus metreina.\n")pituus = float(rivi)pinta_ala = leveys * pituusprint("Huoneen pinta-ala on", pinta_ala, "neliometria")

    main()

    Esimerkki ohjelman suorituksesta:

    Anna huoneen leveys metreina.3.7Anna huoneen pituus metreina.5.3Huoneen pinta-ala on 19.61 neliometria

    Rivinvaihtojen lisminen ei ole mikn Python-ohjelmoinnin vaatima toimenpide,vaan ne on listty ainoastaan tll kurssilla kytettvn automaattisen tarkastus-jrjestelmn toiminnan helpottamiseksi. Jatkossa esitettviss esimerkeiss osassaon tulostuksiin listty rivinvaihdot, osassa ei. Kurssilla palautettavissa harjoitusteh-tviss rivinvaihdot on kuitenkin syyt olla aina mukana (silloin, kun ei tulostetaprint-kskyll, joka lis itse rivinvaihdon).

    2.9.2 Puhelun hinta

    Monessa matkapuhelinliittymss puhelun hinta on koostuu aloitusmaksusta, jokaei riipu puhelun kestosta, sek puhelun kestosta riippuvasta minuuttihinnasta. Seu-raava ohjelma pyyt kyttjlt aloitusmaksun, minuuttihinnan sek puhelun kes-ton minuutteina ja laskee puhelun hinnan. Yksinkertaisuuden vuoksi puhelun kestoannetaan desimaalilukuna. Toinen vaihtoehto olisi antaa kesto kokonaisina minuut-teina ja sekunteina, joista sitten laskettaisiin vastaava kesto desimaalilukuna.

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 16

    def main():print("Ohjelma laskee matkapuhelun hinnan.")rivi = input("Anna puhelun aloitusmaksu.\n")aloitusmaksu = float(rivi)rivi = input("Anna puhelun minuuttihinta.\n")minuuttihinta = float(rivi)rivi = input("Anna puhelun kesto minuutteina.\n")kesto = float(rivi)hinta = aloitusmaksu + kesto * minuuttihintaprint("Puhelun hinta on", hinta, "euroa.")

    main()

    Esimerkki ohjelman suorituksesta:

    Ohjelma laskee matkapuhelun hinnan.Anna puhelun aloitusmaksu.0.049Anna puhelun minuuttihinta.0.079Anna puhelun kesto minuutteina.8.5Puhelun hinta on 0.7205 euroa.

    2.9.3 Aikamuunnoksia

    Vlill tulee vastaa tilanteita, joissa pitempi aika pit ilmaista sekunteina esimer-kiksi erilaisia laskutoimituksia varten. Tm muunnos on helppo totetuttaa pienelltietokoneohjelmalla. Toisaalta monesti on vaikea hahmottaa suoraan, kuinka pitkaika on esimerkiksi 15600 sekuntia. Kun saman ajan ilmaisee tuntien ja minuuttienavulla, tulee aikajakson pituus heti selvksi. Mys tm muunnos on helppo laskeapienen tietokoneohjelman avulla.

    Ensimminen esimerkkiohjelma muuttaa tunteina, minuutteina ja sekunteina anne-tun aikamrn pelkiksi sekunneiksi. Oletetaan, ett aika annetaan sekuntien tark-kuudella (sekuntien osia ei ksitell), jolloin nyt voidaan kytt kokonaislukutyyp-pi int annettujen lukujen ksittelyyn.

    def main():print("Tama ohjelma muuttaa annetun aikajakson pituuden sekunneiksi.")rivi = input("Anna aikajakson tunnit.\n")tunnit = int(rivi)rivi = input("Anna aikajakson minuutit.\n")minuutit = int(rivi)rivi = input("Anna aikajakson sekunnit.\n")sekunnit = int(rivi)aika_sekunteina = tunnit * 3600 + minuutit * 60 + sekunnitprint("Aikajakson pituus on", aika_sekunteina, "sekuntia.")

    main()

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 17

    Esimerkki ohjelman suorituksesta:

    Tama ohjelma muuttaa annetun aikajakson pituuden sekunneiksi.Anna aikajakson tunnit.4Anna aikajakson minuutit.37Anna aikajakson sekunnit.14Aikajakson pituus on 16634 sekuntia.

    Muunnos sekunneista tunneiksi, minuuteiksi ja sekunneiksi on vhn monimutkai-sempi. Tss voidaan kuitenkin kytt hyvksi sit, ett ksitelln kokonaisluku-ja. Kuten aikaisemmin on kerrottu, Pythonissa on tavallisen jakolaskuoperaattorin/ vaihtoehtona operaattori //, jota kytettess kahden kokonaisluvun jakolaskuntulos on kokonaisluku, johon on otettu mukaan vain jakolaskun tuloksen kokonais-osa. Mitn pyristyksi ei siis tehd. Nin johonkin sekuntimrn sisltyvt ty-det tunnit saadaan selville jakamalla tm sekuntimr 3600:lla. Niden tuntienjlkeen ylijneet sekunnit saadaan taas selville ottamalla edellisen jakolaskun ja-kojnns, joka voidaan tehd %-operaattorin avulla. Vastaavalla tavalla saadaanselville jljelle jneisiin sekunteihin sisltyvt kokonaiset minuutit ja sekunnit.

    def main():rivi = input("Anna aikajakson pituus sekunteina.\n")pituus_sekunteina = int(rivi)tunnit = pituus_sekunteina // 3600jaannossekunnit = pituus_sekunteina % 3600minuutit = jaannossekunnit // 60sekunnit = jaannossekunnit % 60print("Pituus on", tunnit, "h", minuutit, "min", sekunnit, "s.")

    main()

    Esimerkki ohjelman suorituksesta:

    Anna aikajakson pituus sekunteina.18756Pituus on 5 h 12 min 36 s.

    Alla on toinen esimerkki ohjelman suorituksesta. Tst nhdn, ett ohjelma ei osaajtt pois tuntia, minuutteja tai sekunteja siin tapauksessa, ett jokin niist onnolla. Ohjelman tulostus ei ole tsskn tapauksessa virheellinen, mutta se voisi ollalyhyempi. Nollien poisjttmiseen tarvitaan kuitenkin valintaksky, joka opetetaanvasta seuraavassa luvussa.

    Anna aikajakson pituus sekunteina.7218Pituus on 2 h 0 min 18 s.

  • LUKU 2. PYTHON-OHJELMOINNIN ALKEITA 18

    2.10 Kommentit

    Ohjelmaan on mys mahdollista list selitysteksti, joka ei vaikuta mitenkn oh-jelman suoritukseen, mutta joka auttaa ohjelmatekstin lukijaa ymmrtmn koo-dia. Tllaisia selitystekstej kutsutaan kommenteiksi. Python-ohjelmissa kommentitmerkitn #-merkill. Kun Python-tulkki ohjelmaa lukiessaan kohtaa #-merkin, sejtt ottamatta huomioon kaiken tmn merkin jlkeen tulevan tekstin rivin lop-puun asti.

    Kommenttien jrkev kytt helpottaa huomattavasti ohjelmaa lukevaa ihmist koo-din ymmrtmisess. Tll on merkityst erityisesti silloin, kun halutaan myhem-min muuttaa ohjelmaa esimerkiksi list siihen uusia ominaisuuksia tai kyttaikaisemmin tehty ohjelmaa jonkin uuden ohjelman pohjana.

    Ohjelman alkuun kannattaa aina list kommentti, joka kertoo, mit ohjelma tekee,kuka sen on kirjoittanut ja koska ohjelmaa on viimeksi muokattu, esimerkiksi:

    # Ohjelma, joka muuttaa kayttajan maileina antaman matkan kilometreiksi.# Kirjoittanut Maija Meikalainen.# Viimeksi muutettu 9.1.2013.

    def main():syote = input("Anna matka maileina: ")mailit = float(syote)kilometrit = 1.6093 * mailitprint("Matka on", kilometrit, "km.")

    main()

    Suuremmissa ohjelmissa kannattaa ohjelman sislle kirjoittaa kommentteja kunkinfunktion merkityksest. Mys funktioiden sisll voi kommentoida kohtia, joidenmerkitys ei selvi helposti koodia lukemalla.

    Kommentteja voi kirjoittaa mys varsinaisen ohjelmarivin loppuun, esimerkiksi

    kilometrit = 1.6093 * mailit #Muuta mailit kilometreiksi kertoimen avulla.

    Pythonin tyyliopas http://www.python.org/dev/peps/pep-0008/ kuitenkin neu-voo kyttmn rivin loppuun kirjoitettavia kommentteja hyvin sstelisti ja suo-simaan omille riveilleen kirjoitettavia kommentteja aina, kun se on jrkev.

    Merkill #-alkavien kommenttien sijaan ohjelmassa olevien kokonaisuuksien kom-mentoimiseen voi kytt dokumentointimerkkijonoja, (engl. documentation strings,docstrings). Niit ei kuitenkaan ksitell tss opetusmonisteessa.

  • Luku 3

    Kontrollirakenteet: valinta jatoisto

    3.1 Valintaksky if

    Thn asti esitetyt ohjelmat ovat aina suorittaneet samat kskyt samassa jrjes-tyksess. Usein kuitenkin haluamme, ett ohjelma toimii eri tilanteissa eri tavoilla,esimerkiksi niin, ett ohjelman toiminta riippuu kyttjn antamista sytteist.

    Oletetaan, ett erseen tilaisuuteen myydn lippuja, jotka maksavat aikuisilta 10euroa ja lapsilta 3 euroa. Alle 18-vuotiaat psevt lasten lipulla. Haluamme kir-joittaa ohjelman, joka kysyy kyttjlt tmn in ja tulostaa sitten lipun hinnan.Hintaa varten voimme mritell muuttujan hinta, mutta sille asetettava arvo riip-puu kyttjn antamasta ist. Jos ik on pienempi kuin 18, pit suorittaa kskyhinta = 3 ja muussa tapauksessa ksky hinta = 10.

    Tllaista tilannetta varten Python-kieless on if-else-rakenne. Rakenteen yleinenmuoto on

    if ehto:ksky1

    else:ksky2

    Tm suoritetaan seuraavasti: Ensin tutkitaan, onko ehto tosi vai ei. Jos ehto on tosi,suoritetaan ksky1. Jos ehto on eptosi, suoritetaan ksky ksky2. Toinen kskyistksky1 ja ksky2 j siis aina suorittamatta. Tss ehto on jokin lauseke, jonkatotuusarvo voidaan tutkia, esimerkiksi ika < 18.

    Lipun hinnan tulostava ohjelma voidaan siis kirjoittaa if-kskyn avulla seuraavasti:

    def main():rivi = input("Kerro ikasi: ")ika = int(rivi)if ika < 18:

    hinta = 3

    19

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 20

    else:hinta = 10

    print("Lipun hinta on", hinta, "euroa")

    main()

    Esimerkki ohjelman suorituksesta:

    Kerro ikasi: 17Lipun hinta on 3 euroa

    Toinen esimerkki:

    Kerro ikasi: 22Lipun hinta on 10 euroa

    If-kskyn ei ole pakko sislt else-osaa. Jos else-osa puuttuu, if-rakenteeseen kuu-luva ksky suoritetaan vain, jos ehto on tosi. Jos ehto on eptosi, siirrytn suoraanohjelman seuraavaan kskyyn.

    Kytetty ehto voi olla mik tahansa lauseke, jonka arvo on True (tosi) tai False(eptosi). Tllaisia lausekkeita voi muodostaa esimerkiksi vertailuoperaattoreidenavulla. Python-kieli tarjoaa seuraavat vertailuoperaattorit:

    > suurempi kuin< pienempi kuin== yhtsuuri kuin!= erisuuri kuin>= suurempi tai yhtsuuri kuin

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 21

    Edell olevassa esimerkiss oli tsmlleen yksi ksky, joka piti suorittaa, jos if-kskynehto oli tosi. Usein kuitenkin halutaan, ett tss tilanteessa suoritetaan useampiksky.

    Esimerkki: henkiln painoindeksi lasketaan siten, ett paino (kiloissa) jaetaan pituu-den (metreiss) nelill. Painoindeksin avulla voidaan ptell, onko henkil ali-, yli-vai normaalipainoinen. Haluamme kirjoittaa ohjelman, joka pyyt kyttjlt pi-tuuden sek painon ja tulostaa sitten henkiln painoindeksin.

    Periaatteessa ohjelma on hyvin yksinkertainen: pyydetn ja luetaan kyttjn painoja pituus, lasketaan painoindeksi ja tulostetaan se. Ongelma on kuitenkin siin, ettjos kyttj antaa vahingossa pituudekseen 0, jakolaskussa syntyy virhetilanne nollalla jako ja ohjelma kaatuu antaen kyttjlle kummallisen virheilmoituksen.Haluamme kuitenkin ohjelman kertovan kyttjlle tss tilanteessa selvsti, miksipainoindeksi ei voi laskea. Ohjelman rakenne on seuraava:

    pyyd ja lue kyttjn paino ja pituus;if pituus != 0:

    laske painoindeksitulosta painoindeksi

    else:ilmoita, ett painoindeksi ei voi laskea

    Haluamme siis suorittaa kaksi eri ksky, jos if-kskyn ehto on tosi. Tm saadaanaikaiseksi kyttmll sisennyksi juuri siten kuin yll olevasta esimerkist nkyy.Kaikki ne kskyt, jotka on sisennetty sisemmlle tasolle kuin if-kskyn ehdon sisl-tv rivi, katsotaan kuuluvaksi samaan if-kskyyn aina niit seuraavaan sisentmt-tmn riviin saakka. Koska pituus ei voi olla myskn negatiivinen, on ohjelmassamuutettu ehto pituus != 0 muotoon pituus > 0. Nin se tulostaa virheilmoituk-sen aina silloin, kun pituus ei ole nollaa suurempi.

    def main():rivi = input("Anna painosi kiloina: ")paino = float(rivi)rivi = input("Anna pituutesi metreina: ")pituus = float(rivi)if pituus > 0.0:

    painoindeksi = paino / (pituus * pituus)print("Painoindeksisi on", painoindeksi)

    else:print("Virheellinen pituus - painoindeksia ei voi laskea")

    main()

    Esimerkki ohjelman suorituksesta:

    Anna painosi kiloina: 74.0Anna pituutesi metreina: 1.81Painoindeksisi on 22.5878330942

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 22

    Toinen esimerkki:

    Anna painosi kiloina: 57.5Anna pituutesi metreina: 0.0Virheellinen pituus - painoindeksia ei voi laskea

    3.1.1 Loogiset operaattorit

    Edellisess painoindeksin laskevassa ohjelmassa tarkistettiin, ett kyttjn anta-ma pituus ei ole nolla. Voi olla hyvinkin jrkev tarkistaa lisksi, ett pituus eiole aivan liian suuri. Ei ole mitenkn eptavallista, ett kyttj ei huomaa sit,ett pituus pitisi antaa metrein. Jos kyttj antaa vahingossa pituuden sentti-metrein, painoindeksist tulee jrjettmn pieni. Tm on helppo est lismllohjelmaan yksi tarkistus lis. Jos esimerkiksi kyttjn antama pituus on vhintn3, voimme olla tysin varmoja siit, ett pituudessa on jokin virhe.

    Aikaisemman ohjelman ehto jos pituus on suurempi kuin 0 pitisi siis muuttaa muo-toon jos pituus on suurempi kuin 0 ja pituus on pienempi kuin 3. Ehto pituus onpienempi kuin 3 on helppo kirjoittaa

    pituus < 3.0

    Nyt tarvitsemme kuitenkin ehdon, joka on tosi silloin, kun molemmat ehdoista jospituus on eri kuin 0 ja pituus on pienempi kuin 3 ovat tosia ja eptosi aina, kuntoinen tai molemmat nist ehdoista ovat eptosia. Tllainen ehto saada aikaiseksikyttmll and- eli ja-operaattoria ehtojen vliss. Aikaisemman ohjelman ehdon

    if pituus > 0:

    sijasta ohjelmaan kirjoitetaankin nyt

    if pituus > 0 and pituus < 3.0:

    Muu ohjelma on tysin sama. Operaattori and on yksi loogisista operaattoreista.Trkeit loogisia operaattoreita on esitelty alla.

    operaattori nimi merkitysand ja tosi, jos molemmat lausekkeet tosiaor tai tosi, jos vhintn toinen lausekkeista tosinot ei tosi, jos seuraava lauseke on eptosi

    Esimerkiksi lausekkeen

    x > 0 or y > 0

    Arvo on True (tosi), jos joko muuttujan x arvo on nollaa suurempi tai muuttujan yarvo on nollaa suurempi tai niiden molempien arvo on suurempi kuin nolla.

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 23

    Operaatioiden and ja or tapauksessa lasketaan ensin ensimmisen (operaattoriaedeltvn) lausekkeen arvo. Jos jo sen perusteella voidaan ptell, ett koko lausek-keen arvon on pakko olla True tai False, ei jlkimmisen lausekkeen arvoa lasketalainkaan. Kytnnss tm tarkoittaa sit, ett jos and-operaattorin ensimmisenoperandin arvo on False, ei toisen operandin arvoa lasketa, vaan koko lausekkeenarvoksi tulee joka tapauksessa False. Vastaavasti, jos or-operaattorin ensimmi-sen operandin arvo on True, ei jlkimmisen operandin arvoa lasketa, vaan kokolausekeen arvoksi tulee aina True.

    Tll on merkityst erityisesti niiss tapauksissa, joissa ensimmisen lausekkeen to-tuusarvosta riippuu se, voidaanko jlkimmisen lausekkeen totuusarvoa laskea lain-kaan. Esimerkiksi lausekkeessa

    (x != 0) and (10 / x > 0)

    laskutoimitus 10 / x aiheuttaa nollalla jakamisen ja koko ohjelman kaatumisen,jos muuttujan x arvo on nolla. Python-ohjelmaan yll olevan lausekkeen voi kui-tenkin kirjoittaa huoletta, koska ensin tutkitaan ensimmisen operandin (x != 0)totuusarvo. Jos kyseinen lauseke on eptosi (eli muuttujan x arvo on 0), ei jlkim-misen operandin totuusarvoa tutkita lainkaan ja jakolasku j nin suorittamatta.

    Luettelon viimeisell operaattorilla not on vain yksi operandi. Esimerkiksi lausek-keen

    not (x < 0)

    arvo on True, jos lausekkeen x < 0 arvo on False, ja pinvastoin.

    Huomautus: Painoindeksiesimerkiss and-operaattorin kytt ei ole vlttmtnt,sill Python-ohjelmissa muuttujan arvon sijoittumista jollekin vlille pystyy tutki-maan mys kirjoittamalla vertailuoperaattorit muuttujan molemmin puolin. Rivi

    if pituus > 0 and pituus < 3.0:

    voidaan siis korvata rivill

    if 0 < pituus < 3.0:

    Nin voidaan tehd kuitenkin vain silloin, kun tutkitaan muuttujan sijoittumistahalutulle vlille. Operaattori and on selvsti monikyttisempi, koska sen avullavoidaan yhdist kaksi mit tahansa ehtoa, joiden ei tarvitse edes sislt samaamuuttujaa.

    3.1.2 Siskkisi if-kskyj

    Mys if-kskyn sisll voi olla toinen if-ksky. Tarkastellaan esimerkki, jossa pai-noindeksin laskun yhteydess halutaan antaa varoitus, jos kyttj on alipainoinen(painoindeksi alle 19) tai ylipainoinen (painoindeksi vhintn 25). Ohjelma voidaantllin kirjoittaa seuraavasti:

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 24

    def main():rivi = input("Anna painosi kiloina: ")paino = float(rivi)rivi = input("Anna pituutesi metreina: ")pituus = float(rivi)if pituus > 0.0 and pituus < 3.0:

    painoindeksi = paino / (pituus * pituus)print("Painoindeksisi on", painoindeksi)if painoindeksi < 19.0:

    print("Olet alipainoinen")if painoindeksi >= 25.0:

    print("Olet ylipainoinen")else:

    print("Virheellinen pituus - painoindeksia ei voi laskea")

    main()

    Esimerkiss sisemmt if-kskyt suoritetaan vain silloin, jos ulomman if-kskyn ehtoon tosi.

    Esimerkki ohjelman suorituksesta:

    Anna painosi kiloina: 48.6Anna pituutesi metreina: 1.6Painoindeksisi on 18.984375Olet alipainoinen

    Joskus if-kskyj joudutaan ketjuttamaan monta perkkin. Tydennetn painoin-deksin laskevaa ohjelmaa siten, ett se tulostaa lopuksi, onko kyttj alipainoinen(painoindeksi alle 19), normaalipainoinen (painoindeksi vhintn 19, mutta alle25), lievsti ylipainoinen (painoindeksi vhintn 25, mutta alle 30), merkittvstiylipainoinen (painoindeksi vhintn 30, mutta alle 35), vaikeasti ylipainoinen (pai-noindeksi vhintn 35, mutta alle 40) vai sairaalloisesti ylipainoinen (painoindeksivhintn 40).

    Ohjelmassa on siis useita ehtoja, joista vain yksi kerrallaan voi olla tosi. Tllin oh-jelman voi toki kirjoittaa kyttmll monta siskkist if-ksky, mutta huomat-tavasti selvemmn ohjelman saa aikaiseksi kyttmll if - elif - else -rakennetta.Rakenteen yleinen muoto on seuraava:

    if ehto1:ksky1

    elif ehto2:ksky2

    elif ehto3:ksky3

    #lis elif-kohtia ja niihin liittyvi kskyj

    else:kskyN

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 25

    Sana elif on lyhenne sanoista else if. Rakenteessa tutkitaan ensin, onko ehto1 tosi.Jos se on, suoritetaan ksky1 eik muita ehtoja tutkita lainkaan. Jos taas ehto1 oneptosi, siirrytn tutkimaan jrjestyksess seuraavien ehtojen totuusarvoja, kunneslydetn ensimminen tosi ehto ja suoritetaan sit vastaava ksky. Jos miknkskyist ei ole tosi, suoritetaan else-kohdassa oleva ksky. Else-kohta voi myspuuttua, jolloin ei suoriteta mitn ksky, jos mikn ehdoista ei ole tosi.

    Painoindeksin laskeva ohjelma on nyt seuraavanlainen:

    def main():rivi = input("Anna painosi kiloina: ")paino = float(rivi)rivi = input("Anna pituutesi metreina: ")pituus = float(rivi)if pituus > 0.0 and pituus < 3.0:

    painoindeksi = paino / (pituus * pituus)print("Painoindeksisi on", painoindeksi)if painoindeksi < 19.0:

    print("Olet alipainoinen")elif painoindeksi < 25.0:

    print("Painosi on normaali")elif painoindeksi < 30.0:

    print("Olet lievasti ylipainoinen")elif painoindeksi < 35.0:

    print("Olet merkittavasti ylipainoinen")elif painoindeksi < 40.0:

    print("Olet vaikeasti ylipainoinen")else:

    print("Olet sairaalloisesti ylipainoinen")else:

    print("Virheellinen pituus - painoindeksia ei voi laskea")

    main()

    Ehdoissa ei nyt tarvitse lainkaan tutkia, onko painoindeksi suurempi kuin jokin ala-raja, sill edellisten if- ja elif-kohtien ehdot pitvt huolen siit, ett jotain ehtoatutkitaan vain silloin, jos painoindeksi on edellisten kohtien rajaa suurempi. Esi-merkisi ehdon painoindeksi < 35.0 totuusarvoa tutkitaan vain siin tapauksessa,ett kaikki edelliset ehdot ovat olleet eptosia, jolloin painoindeksin on pakko ollavhintn 30.

    Esimerkki ohjelman suorituksesta:

    Anna painosi kiloina: 49.0Anna pituutesi metreina: 1.6Painoindeksisi on 19.140625Painosi on normaali

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 26

    3.2 Toistoksky

    Useissa tietokoneohjelmissa samaa toimenpidett pit toistaa monta kertaa. Aja-tellaan tasalyhenteist lainaa varten tehtv asuntolainalaskuria, joka pyyt ensinkyttjlt lainasumman, laina-ajan ja korkoprosentin. Tmn jlkeen ohjelman ha-lutaan tulostavan luettelon eri kuukausina maksettavista lainanhoitokuluista (lyhen-nys + korko yhteens). Jos laina on tasalyhenteinen, maksettava lyhennys on jokakuukausi sama, mutta korkoer vaihtelee sen mukaan, paljonko lainaa on jljell.

    Ohjelman on siis laskettava jokaista kuukautta kohti sen hetkinen poma, tllepomalle kuukauden aikana kertynyt korko ja lyhennysern ja kuukauden korkoe-rn summa. Jos laina-aika on 10 vuotta, pit tm laskutoimitus toistaa 120 ker-taa. Olisi ikv kirjoittaa samat kskyt ohjelmaan 120 kertaa perkkin. Lisksitm lhestymistapa ei edes toimisi, jos kyttj saisi antaa vapaasti haluamansalaina-ajan, koska kirjoitettavien kskyjen mr riippuisi aina laina-ajasta.

    Tllaisia tilanteita varten useimmissa ohjelmointikieliss on toistokskyj. Toisto-kskyn avulla voidaan ohjelmaa pyyt toistamaan jotain toista ksky tai ksky-jonoa niin kauan kuin jokin ohjelmoijan antama ehto on tosi.

    Python-kieless on kaksi erilaista toistoksky: while ja for. Seuraavaksi tar-kastellaan niden kskyjen toimintaa. Ennen kuin lhdemme katsomaan asunto-lainalaskurin toteuttamista niden kskyjen avulla, tutkimme kskyjen rakennettayksinkertaisemman esimerkin kautta.

    3.2.1 Toistoksky while

    While-kskyn yleinen rakenne on

    while ehto:ksky

    Kun ohjelmassa suoritetaan tllaist ksky, toimitaan seuraavasti: Ensin tarkas-tetaan, onko ehto tosi. Jos se on eptosi, siirrytn suoraan ohjelmassa eteenpinwhile-rakenteen sisll olevan kskyn (tai kskyjen) ohi sen jlkeen tulevaan koh-taan. Jos taas ehto on tosi, suoritetaan ksky. Tmn jlkeen tarkastetaan uudel-leen, onko ehto tosi. Jos se on tosi, suoritetaan ksky jlleen. Sen jlkeen tarkaste-taan taas, onko ehto tosi. Nin jatketaan, kunnes tullaan siihen tilanteeseen, ettehto on eptosi. Silloin lopetaan while-kskyn suoritus ja siirrytn ohjelmassaeteenpin.

    Toistettavia kskyj voi olla joko yksi tai useita perkkin. Jlleen sisennysten avullaosoitetaan, mitk kskyt kuuluvat toistettavien kskyjen sarjaan. Ehdon totuusar-vo tarkistetaan kuitenkin vain ennen ensimmisen kskyn suoritusta ja aina kokokskysarjan suorituksen jlkeen, ei siis kskysarjaan kuuluvien kskyjen vliss.

    Tarkastallaan ensimmisen esimerkkin ohjelmaa, joka pyyt kyttjlt 10 ko-konaislukua ja laskee niiden keskiarvon.

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 27

    def main():print("Anna 10 kokonaislukua, lasken niiden keskiarvon")i = 0summa = 0while i < 10:

    rivi = input("Anna seuraava luku: ")luku = int(rivi)summa = summa + lukui = i + 1

    keskiarvo = summa / 10print("Niiden keskiarvo on", keskiarvo)

    main()

    Ohjelmassa kytetn muuttujaa i pitmn kirjaa siit, montako lukua on jo luet-tu. Ennen toistokskyn alkua i:lle annetaan arvo 0 ja jokaisella kierroksella i:narvoa kasvatetaan yhdell. Koska lukuja halutaan lukea 10 kappaletta, on toisto-kskyn suorittamista jatkettava niin kauan kuin i:n arvo on pienempi kuin 10.

    Tarvitaan mys muuttuja, johon kertn jo luettujen lukujen summa. Thn tar-koitukseen ohjelmassa kytetn muuttujaa summa, joka myskin alustetaan nollak-si ennen toistokskyn alkua. Toistokskyn jokaisella kierroksella kyttjlt luettuluku listn muuttujan summa vanhaan arvoon.

    Toistokskyn ptytty lasketaan keskiarvo jakamalla summa luettujen lukujenmrll.

    Esimerkki ohjelman suorituksesta:

    Anna 10 kokonaislukua, lasken niiden keskiarvonAnna seuraava luku: 12Anna seuraava luku: 15Anna seuraava luku: 42Anna seuraava luku: 33Anna seuraava luku: 76Anna seuraava luku: 45Anna seuraava luku: 22Anna seuraava luku: 12Anna seuraava luku: 34Anna seuraava luku: 33Niiden keskiarvo on 32.4

    Edellisess ohjelmassa luettavien lukujen mrksi on mrtty 10. Jos lukumrhalutaan muuttaa, pit muuttaa itse ohjelmaa. Ohjelma on kuitenkin kirjoitettuniin, ett muutos pit tehd kolmeen eri paikkaan: kyttjlle annettavaan al-kuohjeeseen, toistokskyn ehtoon ja keskiarvon laskevaan lausekkeeseen. On paljonparempi kirjoittaa ohjelma niin, ett luettavien lukujen mr tallennetaan muut-tujaan, jota sitten kytetn ohjelmassa aina siell, miss mr tarvitaan. Tllinlukumr on tarvittaessa helppo muuttaa. Muutos tarvitsee tehd vain yhteenpaikkaan, ja tuon paikan lytminen on helppoa silloinkin, kun ohjelma on pitk.

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 28

    Tllaista muuttujaa kutsutaan vakioksi ja sen nimi kirjoitetaan isoilla kirjaimilla ker-tomaan siit, ett ohjelman suorituksen ei ole tarkoitus muuttaa tmn muuttujanarvoa sen jlkeen, kun ohjelmassa on annettu muuttujalle vakioalkuarvo. Muutettuohjelma on esitetty alla.

    def main():LKM = 10print("Anna", LKM, "kokonaislukua, lasken niiden keskiarvon")i = 0summa = 0while i < LKM:

    rivi = input("Anna seuraava luku: ")luku = int(rivi)summa = summa + lukui = i + 1

    keskiarvo = summa / LKMprint("Niiden keskiarvo on", keskiarvo)

    main()

    Seuraava versio ohjelmasta on sellainen, ett kyttj voi itse kertoa, kuinka mon-ta lukua hn antaa. Ohjelma pyyt aluksi kyttjlt annettavien lukujen luku-mrn ja tallentaa sen muuttujaan lukujen_maara. Sen jlkeen ohjelma pyyttoistokskyn avulla nin monta lukua ja laskee lopuksi niiden keskiarvon. Koska lu-kujen mr pyydetn kyttjlt, on ohjelmaan listty tarkistus, jolla vltetnohjelman kaatuminen jakolaskussa siin tapauksessa, ett lukujen mr on 0.

    def main():print("Lasken keskiarvon antamistasi kokonaisluvuista.")rivi = input("Anna lukujen maara: ")lukujen_maara = int(rivi)i = 0summa = 0while i < lukujen_maara:

    rivi = input("Anna seuraava luku: ")luku = int(rivi)summa = summa + lukui = i + 1

    if lukujen_maara > 0:keskiarvo = summa / lukujen_maaraprint("Niiden keskiarvo on", keskiarvo)

    else:print("Et antanut yhtaan lukua.")

    main()

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 29

    Lasken keskiarvon antamistasi kokonaisluvuista.Anna lukujen maara: 5Anna seuraava luku: 2Anna seuraava luku: 4Anna seuraava luku: 8Anna seuraava luku: 8Anna seuraava luku: 10Niiden keskiarvo on 6.4

    Tsskin versiossa on kuitenkin se ongelma, ett kyttjn on etukteen tiedettv,montako lukua hn haluaa antaa. Jos lukuja on paljon, niiden laskeminen voi ollatylst. Tllin kyttjn kannalta olisi parempi, ett hn voisi antaa lukuja niinkauan kuin niit riitt ja sitten kun luvut ovat lopussa, osoittaa jollain sopivallaarvolla lukujen loppuneen.

    Jos esimerkiksi tiedetn, ett kaikki annettavat luvut ovat suurempia tai yhtsuu-ria kuin nolla, voi kyttj osoittaa lukujen loppuneen antamalla negatiivisen luvun.Ohjelma kirjoitetaan niin, ett se lopettaa lukujen lukemisen ensimmisen tllaisenluvun saatuaan. Viimeiseksi luettua negatiivista lukua ei tllin oteta mukaan kes-kiarvoa laskettaessa. Ohjelma toteutetaan siten, ett ensimminen luku luetaan joennen toistokskyn alkua ja toistoksky jatketaan niin kauan kuin viimeiseksi luet-tu luku on vhintn nolla. Koska luettavien lukujen mr ei tiedet etukteen,on se laskettava.

    def main():print("Lasken keskiarvon antamistasi ei-negatiivisista kokonaisluvuista.")print("Lopeta negatiivisella luvulla.")lukujen_maara = 0summa = 0rivi = input("Anna ensimmainen luku: ")luku = int(rivi)while luku >= 0:

    lukujen_maara = lukujen_maara + 1summa = summa + lukurivi = input("Anna seuraava luku: ")luku = int(rivi)

    if lukujen_maara > 0:keskiarvo = summa / lukujen_maaraprint("Niiden keskiarvo on", keskiarvo)

    else:print("Et antanut yhtaan ei-negatiivista lukua.")

    main()

    Esimerkki ohjelman suorituksesta:

    Lasken keskiarvon antamistasi ei-negatiivisista kokonaisluvuista.Lopeta negatiivisella luvulla.Anna ensimmainen luku: 24

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 30

    Anna seuraava luku: 12Anna seuraava luku: 30Anna seuraava luku: 13Anna seuraava luku: -5Niiden keskiarvo on 19.75

    3.2.2 Esimerkki: valintaksky toistokskyn sisll

    Toistokskyn sisll voi olla mit tahansa kskyj, esimerkiksi toinen toistokskytai if-ksky. Seuraavassa esimerkiss toistokskyn sisll on if-ksky.

    Tarkastellaan seuraavaa tilannetta: kyttj sytt ohjelmalle eri pivien lmpti-loja ja sademri. Ohjelman halutaan laskevan kaikkien lmptilojen keskiarvon se-k sadepivien lukumrn. Sadepivksi katsotaan piv, jonka sademr on ollutvhintn 1.0 mm. Ohjelma pyyt aluksi niiden pivien lukumrn, joiden tiedotsytetn ohjelmalle. Sitten ohjelma lukee while-kskyn sisll yhden pivn lm-ptilan ja sademrn. If-kskyn avulla tutkitaan, onko viimeksi luettu sademrvhintn 1.0. Jos se on, sadepivien lukumr kasvatetaan yhdell. Toistoks-kyn jlkeen ohjelma tulostaa lmptilojen keskiarvon ja sadepivien lukumrn.Nit kskyj ei en kirjoiteta toistokskyn sislle, koska tulostusten halutaan ta-pahtuvan vasta siin vaiheessa, kun kaikki pivt on jo kyty lpi ja toistokskypttynyt.

    def main():print("Ohjelma keraa saatilastoja.")syote = input("Monenko paivan tiedot haluat antaa? ")paiva_lkm = int(syote)i = 0sadepaivien_lkm = 0lamposumma = 0.0while i < paiva_lkm:

    syote = input("Anna paivan lampotila (C): ")lampotila = float(syote)lamposumma += lampotilasyote = input("Anna saman paivan sademaara (mm): ")sademaara = float(syote)if sademaara >= 1.0:

    sadepaivien_lkm += 1i += 1

    if paiva_lkm == 0:print("Et antanut yhdenkaan paivan tietoja.")

    else:keskiarvo = lamposumma / paiva_lkmprint("Lampotilojen keskiarvo on", keskiarvo, "C.")print("Sadepaivia oli", sadepaivien_lkm, "kpl.")

    main()

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 31

    Esimerkki ohjelman suorituksesta:

    Ohjelma keraa saatilastoja.Monenko paivan tiedot haluat antaa? 8Anna paivan lampotila (C): 12.0Anna saman paivan sademaara (mm): 3.0Anna paivan lampotila (C): 18.5Anna saman paivan sademaara (mm): 0.0Anna paivan lampotila (C): 22.1Anna saman paivan sademaara (mm): 0.0Anna paivan lampotila (C): 11.5Anna saman paivan sademaara (mm): 1.5Anna paivan lampotila (C): 9.0Anna saman paivan sademaara (mm): 0.5Anna paivan lampotila (C): 16.0Anna saman paivan sademaara (mm): 0.0Anna paivan lampotila (C): 13.3Anna saman paivan sademaara (mm): 4.5Anna paivan lampotila (C): 18.0Anna saman paivan sademaara (mm): 0.0Lampotilojen keskiarvo on 15.05 C.Sadepaivia oli 3 kpl.

    3.2.3 Iteraatioesimerkki

    Insinrimatematiikassa trmtn usein tilanteeseen, jossa jokin yhtl pit rat-kaista iteroimalla, koska yhtllle ei ole suoraa ratkaisukaavaa. Iteroinnissa aluksiarvataan yhtln juurelle (ratkaisulle) jokin arvo. Tmn jlkeen arvaus sijoitetaansopivaan lausekkeeseen ja nin saatua arvoa kytetn parempana arvauksena. Sesijoitetaan edelleen lausekkeeseen, jolloin saadaan viel parempi arvaus ja niin edel-leen, kunnes arvaus on riittvn lhell oikeaa arvoa. Aina arvaus ei parane jokakierroksella, mutta jos iterointimenetelm on oikein valittu, yleens saadut arvauk-set vhitellen lhenevt oikeaa ratkaisua.

    Tarkastellaan esimerkkin kyttjn antaman luvun x nelijuuren laskemista New-tonin iteraatiolla. Nelijuuren laskemista varten Python-kirjastoon on kirjoitettuvalmiiksi oma funktio, joten esimerkkiohjelmamme ei ole sen vuoksi mitenkn vlt-tmtn. Se on tss valittu kuitenkin esimerkiksi iteroinnista yksinkertaisuutensavuoksi.

    Haluamme siis lyt luvun y siten, ett y =x. Toisin sanoen on etsittv funktion

    f(y) = y2x nollakohta. Newtonin iteraatio perustuu yleisesti siihen, ett jos meillon funktion f(y) nollakohdalle arvaus yn, niin parempi arvaus yn+1 saadaan kaavalla

    yn+1 = yn f(yn)f (yn)

    miss f (y) tarkoittaa funktion f derivaattaa muuttujan y suhteen. Kaava on saatusiit, ett tarkastellaan funktion f(y) tangenttia kohdassa yn ja on laskettu, misskohdassa tangenttisuora leikkaa x-akselin.

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 32

    Kun annettuun kaavaan sijoitetaan funktio f(y) = y2 x, ja sievennetn saatulauseke, saadaan iterointikaavaksi

    yn+1 =12(yn +

    x

    yn)

    Tmn perusteella voidaan siis laskea muuttujan x nelijuurelle parempi arvausyn+1, kun vanha arvaus on yn. Iteraatiossa lhdetn liikkeelle mist tahansa posi-tiivisesta alkuarvauksesta, esimerkiksi ykksest.

    Ohjelma tarvitsee viel tiedon siit, koska saatu arvaus on riittvn hyv eli koskaiterointi pit lopettaa. Yksi yleinen menetelm on tarkastella kahden perttisenarvauksen vlist eroa ja lopettaa silloin, kun tm ero on tarpeeksi pieni. Mene-telm toimii vain silloin, kun arvaus joka kierroksella lhenee oikeaa arvausta. Josarvaukset voivat lhenty jotain paikallista maksimia tai minimi, joka ei ole kuiten-kaan oikean ratkaisun lhell, tll kriteerill saatu tulos voi olla kaukana oikeasta.Nelijuuren hakemiseen tm kriteeri kuitenkin sopii.

    Kun tutkitaan, kuinka lhell uusi arvaus on lhell edellist arvausta, on ktevkytt apuna itseisarvon laskemista. Etukteen ei ole tietoa siit, onko uusi arvaussuurempi vai pienempi kuin edellinen arvaus. Tmn vuoksi on helpointa tehd niin,ett lasketaan kahden perkkisen luvun vlinen erotus ja otetaan siit itseisarvo.Itseisarvon laskemiseen Pythonissa valmiina funktio abs. Luvun arvo itseisarvo voi-daan laskea kirjoittamalla abs(arvo).

    Nelijuuren laskeva ohjelma on alla. Koska nelijuurta ei ole mritelty negatiivisilleluvuille, ohjelma tarkistaa ensin, ett kyttjn antama luku ei ole negatiivinen, jalaskee nelijuuren vain ei-negatiivisille luvuille.

    def main():TARKKUUS = 0.0001rivi = input("Minka luvun neliojuuri lasketaan? ")x = float(rivi)if x < 0:

    print("Neliojuurta ei ole maaritelty negatiivisille luvuille")else:

    arvaus = 1.0uusi_arvaus = 0.5 * (arvaus + x / arvaus)while abs(uusi_arvaus - arvaus) > TARKKUUS:

    arvaus = uusi_arvausuusi_arvaus = 0.5 * (arvaus + x / arvaus)

    print("Luvun", x, "neliojuuri on", uusi_arvaus)

    main()

    Esimerkki ohjelman suorituksesta:

    Minka luvun neliojuuri lasketaan? 57.0Luvun 57.0 neliojuuri on 7.54983443527

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 33

    Toinen esimerkki:

    Minka luvun neliojuuri lasketaan? -9.0Neliojuurta ei ole maaritelty negatiivisille luvuille

    3.2.4 Toistoksky for ja range-funktio

    Toinen Python-kieless kytettv toistoksky on for. Se on tarkoitettu tilanteisiin,jossa kydn lpi jonkin lukujonon tai rakenteen kaikki alkiot jrjestyksess. Pe-rehdymme for-kskyn kyttmiseen eri rakenteiden yhteydess myhemmin, kunnit rakenteita (lista, merkkijonot, sanakirja) esitelln tarkemmin. Tss vaihees-sa tarkastellaan kuitenkin lyhyesti for-kskyn kytt lukujonojen yhteydess.

    Python-kieless saa generoitua kokonaislukujonon haluamaltaan vlilt funktionrange avulla. Ksky range(n) generoi lukujonon, joka sislt jrjestyksess kaikkikokonaisluvut nollasta n-1:een saakka. Jos nyt kirjoitetaan ksky

    for i in range(n):kasky

    tarkoittaa se: suorita kasky vuorotellen jokaiselle i:n arvolle, joka kuuluurange(n):n generoimaan lukujonoon. Ensimmisell kierroksella siis kasky suori-tetaan niin, ett i:n arvo on 0, toisella kierroksella i:n arvo on 1, kolmannella 2 janiin edelleen, kunnes viimeisell kierroksella i:n arvo on n-1. Yhden kskyn sijaantoistettavana voi jlleen olla useamman kskyn jono, ja sisennysten avulla osoite-taan, mik ohjelman osa kuuluu toistettavaan osaan. Esimerkiksi alla oleva ohjelmatulostaa 6:n kertotaulun (niin, ett mys laskun 0 * 6 tulos on mukana):

    def main():for i in range(11):

    tulo = i * 6print(i, "* 6 =", tulo)

    main()

    Ohjelman tulostus siis nytt seuraavalta:

    0 * 6 = 01 * 6 = 62 * 6 = 123 * 6 = 184 * 6 = 245 * 6 = 306 * 6 = 367 * 6 = 428 * 6 = 489 * 6 = 5410 * 6 = 60

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 34

    Joka kierroksella laskettavaa tuloa ei tarvitse vlttmtt tallentaa muuttujaan,vaan kertolasku voidaan antaa mys suoraan tulostuskskyss:

    def main():for i in range(11):

    print(i, "* 6 =", i * 6)

    main()

    Ohjelman tulostus on tsmlleen sama kuin edell.

    Huomautus: ksite lukujono ei ole tysin oikea, kun puhutaan range-kskyn suori-tuksesta. Oikea Pythonissa kytettv termi on iteraattori. Toistokskyn for ja ks-kyn range suorituksen ymmrtmiseen riitt kuitenkin se, ett kuvittelee range-kskyn tekevn lukujonon, jota for-kskyss kydn lpi.

    Toistettaviin kskyihin voi kuulua mit tahansa Python-kielen kskyj, esimerkiksiif-kskyj tai toisia toistokskyj. Seuraavassa esimerkkiohjelmassa kyttj antaahaluamansa mrn lukuja (mr kysytn ensin kyttjlt), ja ohjelma laskeeannetuista luvuista positiivisten lukujen summan. Negatiivisia lukuja ei siis otetasummaan mukaan. Toistokskyn sisll kytetn if-ksky tarkistamaan, onkoviimeksi luettu luku positiivinen.

    def main():rivi = input("Anna lukujen maara.\n")lkm = int(rivi)summa = 0print("Anna luvut yksi kerrallaan.")for i in range(lkm):

    rivi = input()luku = float(rivi)if luku > 0:

    summa += lukuprint("Positiivisten lukujen summa on", summa)

    main()

    Tss ohjelmassa muuttujaa i ei ole kytetty toistokskyn sisll mitenkn. Senavulla pidetn vain huoli siit, ett kierroksia suoritetaan tsmlleen kyttjn an-tama mr, joka on ohjelman alussa tallennettu lkm-muuttujaan. Summan tulosta-vaa rivi ohjelman lopussa ei ole en sisennetty for-kskyn sisn, koska tulostustehdn vasta toistokskyn ptytty, ei joka kierroksella.

    Funktio range luo siis oletusarvoisesti lukujonon, jonka ensimminen alkio on 0.Jos lukujonon halutaan alkavan jostain muusta luvusta, voidaan se tehd antamallarange-funktiolle sulkujen sisll ensin haluttu lhtarvo, esimerkiksi range(1,n)tuottaa lukujonon, joka sislt kokonaisluvut luvusta 1 lukuun n-1 asti. Seuraavaohjelma tulostaa kuuden kertotaulun niin, ett siin ei ole mukana rivi, joka sisltkertolaskun 0 * 6.

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 35

    def main():for i in range(1, 11):

    print(i, "* 6 =", i * 6)

    main()

    Oletusarvoisesti range-funktio luo lukujonon, joka sislt kaikki halutun vlin ko-konaisluvut jrjestyksess. Jos kuitenkin halutaan, ett lukujonossa perkkistenlukujen erotus on suurempi kuin 1, voidaan haluttu vli antaa range-funktiolle kol-mantena tietona. range(alaraja, ylaraja, vali) tuottaa lukujonon, jossa esiin-tyvt vali:n vlein olevat luvut alkaen alarajasta ja pttyen viimeiseen lukuun,joka on pienempi kuin ylaraja. Esimerkiksi ksky

    for i in range(5, 19, 3):print(i)

    Tulostaa

    58111417

    3.2.5 Tulostuksen muotoilusta

    Ennen kuin jatketaan toistokskyist ja niit kyttvist esimerkeist, katsotaanvhn sit, miten ohjelmoija voi vaikuttaa ohjelman tulostuksen muotoiluun.

    Thnastissa esimerkeiss desimaaliluvut on tulostettu sill tarkkuudella, mitPython-tulkki on oletuksena kyttnyt. Kytnnss tm on tarkoittanut sit, etttulostustetuissa luvuissa on usein ollut tarpeettoman monta desimaalia. Tulostukses-ta tulisi selvsti siistimpi, jos desimaalipisteen jlkeen tulevien numeroiden mrrajoitettaisiin. Tm voidaan tehd tulostuksen muotoilun avulla.

    Muotoilun avulla voidaan mys mritell, miten leven kenttn kokonaisluvutja merkkijonot tulostetaan. Kentll tarkoitetaan sit aluetta, joka tulostuksessakytetn jonkin asian esittmiseen. Jos kentn leveydeksi on mritelty esimerkik-si 8, niin luvulle varataan tulostuksessa 8 merkin levyinen alue, vaikka itse lukuveisikin vain 2 merkki. Joko ennen lukua tai sen jlkeen kirjoitetaan ylimrisivlilyntej. (Jos luku on niin suuri, ett se ei mahdu sille varattuun kenttn, osaaluvusta ei kuitenkaan jtet tulostamatta, vaan luvun annetaan kytt enemmntilaa kuin mit sille on muotoilussa mrtty.) Kentn leveyden mrittely tar-vitaan esimerkiksi silloin, kun halutaan tulostaa useita arvoja perkkisille riveilleniin, ett vastaavat arvot tulevat rivill aina samaan kohtaan.

    Kun halutaan vaikuttaa print-kskyll tulostettavan rivin muotoiluun, kirjoitetaanensin lainausmerkkien sislle tulostettavalle riville tuleva vakioteksti. Tmn tekstinkeskelle listn aaltosulut ja niiden sislle muotoilumre niihin paikkoihin, joihintulostuksessa halutaan tulevan jonkin muuttujan arvo. Aaltosulut ja niiden sislloleva muotoilumre osoittavat, mihin paikkaan muuttujan arvo tulee tulostettavas-sa tekstiss, ja lisksi ne kertovat, miten tulostettava arvo muotoillaan, esimerkiksi

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 36

    kuinka leve kentt arvolle varataan ja montako desimaalia desimaaliluvusta tulos-tetaan. Lainausmerkeiss olevan tekstin jlkeen kirjoitetaan piste, ksky format, jasen jlkeen luetellaan sulkujen sisll niiden muuttujien nimet, joiden arvot rivillhalutaan tulostaa. Rivi tulostettaessa aaltosulut ja niiden sisll olevat muotoi-lumreet korvataan luettelossa olevien muuttujien arvoilla niin, ett ensimmisetaaltosulut sisltineen korvataan luettelon ensimmisen muuttujan arvolla, toisetaaltosulut sisltineen luettelon toisen muuttujan arvolla jne.

    Muotoilumre alkaa kaksoispisteell :. Sen jlkeen siin kerrotaan ensin arvollevarattavan kentn leveys kokonaislukuna. Leveys voidaan jtt mys pois, jolloinarvolle varataan sen tarvitsema tila (esimerkiksi 4-numeroiselle kokonaisluvulle 4merkin levyinen kentt). Desimaalilukuja koskevissa muotoilumreiss tulee seu-raavaksi piste ja tmn jlkeen toinen luku, joka kertoo, kuinka monta numeroa esi-tetn desimaalipisteen jlkeen. Viimeisen muotoilumress on mrittelykirjain,joka kertoo, mink tyyppinen arvo kohtaan tulee, esimerkiksi d, kun on kysymykses-s kokonaisluku, s, jos kysymyksess on merkkijono ja f, e tai g, jos kysymyksesson desimaaliluku. (Muotoilumreiss voi olla mys muita osia tai muita kirjaimiaerilaisia tyyppej varten. Niit ei esitet tss sen tarkemmin, mutta kiinnostunutlukija voi tutkia asiaa tarkemmin Pythonin omasta dokumentaatiosta.)

    Seuraavaksi joitakin esimerkkej muotoilumreiden kytst ja niiden selityksi.Esimerkit eivt ole kokonaisia ohjelmia, vaan Python-tulkille on annettu yksittisikskyj kappaleessa 2.1 kuvatulla tavalla.

    >>> kertoja = 5>>> kerrottava = 8>>> tulos = kertoja * kerrottava>>> print("{:3d} kertaa {:3d} on {:6d}".format(kertoja, kerrottava, tulos))

    5 kertaa 8 on 40

    Tss on kerrottu, ett tulostettavaan tekstiin tulee ensin kokonaislukuarvo, jollevarataan 3 merkin levyinen kentt, sen jlkeen teksti "kertaa ", sitten kokonaislu-kuarvo, jolle varataan 3 merkin levyinen kentt, sen jlkeen teksti "on "ja lopuksikokonaislukuarvo, jolle varataan kuuden merkin levyinen kentt. Tulostuksessa en-simmisen muotoilukoodin paikalle sijoitetaan muuttujan kertoja arvo, toisen koo-din paikalle muuttujan kerrottava arvo ja kolmannen koodin paikalle muuttujantulos arvo.

    Huomautus: oikeastaan muotoilussa on kysymys siit, ett print-kskyss anne-tulle merkkijonolle kutsutaan format-nimist metodia, joka suorittaa tulostettavanmerkkijonon muotoilun. Tt ei kuitenkaan tarvitse viel ymmrt tss vaiheessa,vaan asiaan palataan sitten, kun ksitelln olioita.

    >>> enimi1 = "Matti">>> snimi1 = "Virtanen">>> palkka1 = 2800>>> enimi2 = "Tiina-Maija">>> snimi2 = "Pomo">>> palkka2 = 11000>>> print("{:15s} {:15s} {:5d} euroa".format(snimi1, enimi1, palkka1))Virtanen Matti 2800 euroa

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 37

    >>> print("{:15s} {:15s} {:5d} euroa".format(snimi2, enimi2, palkka2))Pomo Tiina-Maija 11000 euroa

    Tss on muotoilukoodien avulla mritelty merkkijonojen ja kokonaisluvun kentnleveys. Nin perkkin tulostettavilla riveill sarakkeet menevt pllekkin, vaikkamerkkijonojen pituus ja lukujen suuruus vaihtelevat. Oletuksen mukaisesti merk-kijonoja sisltvt sarakkeet on tasattu niin, ett niiden vasen reuna on samassakohdassa, ja lukuja sisltvt sarakkeet niin, ett niiden oikea reuna on samassakohdassa. Jos halutaan st lukujen tulostus kentn vasempaan reunaan, listnmuotoilumreeseen :-merkin jlkeen merkki . Alla on tst esimerkkej:

    >>> print("{:>15s} {:>15s} {:15s} {:>15s} {:

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 38

    Jos ei ole tietoa tulostettavan desimaaliluvun suuruusluokasta, voi kytt m-rittelykirjainta g. Tllin luku tulostetaan ilman eksponenttiosaa, jos nin voidaansiististi tehd ja eksponenttiosan kanssa, jos luku on itseisarvoltaan hyvin pieni taisuuri. Mrittelykirjainta g kytettess pisteen jlkeen tuleva luku ei kuitenkaanen mr desimaalipisteen jlkeen tulevien lukujen lukumr, vaan tulostuk-sessa esiintyvien merkitsevien numeroiden lukumr.

    >>> pieni_luku = 1.2308e01>>> suuri_luku = 14.5e20>>> tulo = pieni_luku * suuri_luku>>> print("Kun kerrotaan {:5.4g} ja {:8.4g}, saadaan {:10.4g}".format(... pieni_luku, suuri_luku, tulo))Kun kerrotaan 12.31 ja 1.45e+21, saadaan 1.785e+22

    Tulostusta muotoiltaessa tulostettavan arvon ei tarvitse olla suoraan muuttujan ar-vona, vaan format-osan sulkujen sisll voidaan antaa tulostettavaksi mit tahansalausekkeita, esimerkiksi

    >>> korko = 2.5>>> paaoma = 12000>>> print("Saat korkoa {:.2f} eur".format(korko / 100.0 * paaoma))Saat korkoa 300.00 eur

    3.2.6 Asuntolainaesimerkki

    Tarkastellaan alussa mainittua esimerkki. Halutaan kirjoittaa ohjelma, joka tulos-taa tasalyhenteisen lainan maksusuunnitelman eli kuukausittain maksettavat korko-ja lyhennysert. Ohjelma pyyt kyttjlt laina-ajan vuosina, lainasumman se-k korkoprosentin. Yksinkertaisuuden vuoksi oletetaan, ett korkoprosentti pysyysamana koko laina-ajan.

    Kuukausittainen lyhennyser saadaan jakamalla lainasumma laina-aikaan kuulu-vien kuukausien mrll. Lyhennys pysyy koko laina-ajan samana. Kuukausittainmaksettava korkoer taas vaihtelee sen mukaan, kuinka paljon lainan pomaa onviel jljell. Jokaista kuukautta kohti lasketaan jljell olevan poman aiheuttamakorkoer ja tmn jlkeen vhennetn lyhennyser pomasta. Ohjelma on kirjoi-tettu alla while-kskyn avulla. Yksinkertaisuuden vuoksi pyristysvirheiden mah-dollisuutta ei ole otettu huomioon, vaan yhteens takaisin maksettava lainapomavoi poiketa muutamalla sentill alkuperisest lainasummasta.

    def main():print("Ohjelma laskee asuntolainan kuukausierat.")rivi = input("Anna lainasumma: ")lainasumma = float(rivi)rivi = input("Anna laina-aika vuosina: ")laina_aika = int(rivi)if laina_aika < 1:

    print("Liian lyhyt laina-aika")

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 39

    else:kk_lkm = 12 * laina_aikarivi = input("Anna korkoprosentti: ")korko = float(rivi)lyhennys = lainasumma / kk_lkmpaaoma = lainasummai = 0print(" lyhennys korko yhteensa")while i < kk_lkm:

    i = i + 1korkoera = korko / 1200.0 * paaomapaaoma = paaoma - lyhennyskuukausiera = korkoera + lyhennysprint("{:2d}. {:8.2f} {:8.2f} {:8.2f}".format(

    i, lyhennys, korkoera, kuukausiera))

    main()

    Esimerkki ohjelman suorituksesta:

    Ohjelma laskee asuntolainan kuukausierat.Anna lainasumma: 20000Anna laina-aika vuosina: 2Anna korkoprosentti: 5.5

    lyhennys korko yhteensa1. 833.33 91.67 925.002. 833.33 87.85 921.183. 833.33 84.03 917.364. 833.33 80.21 913.545. 833.33 76.39 909.726. 833.33 72.57 905.907. 833.33 68.75 902.088. 833.33 64.93 898.269. 833.33 61.11 894.44

    10. 833.33 57.29 890.6211. 833.33 53.47 886.8112. 833.33 49.65 882.9913. 833.33 45.83 879.1714. 833.33 42.01 875.3515. 833.33 38.19 871.5316. 833.33 34.37 867.7117. 833.33 30.56 863.8918. 833.33 26.74 860.0719. 833.33 22.92 856.2520. 833.33 19.10 852.4321. 833.33 15.28 848.6122. 833.33 11.46 844.7923. 833.33 7.64 840.9724. 833.33 3.82 837.15

  • LUKU 3. KONTROLLIRAKENTEET: VALINTA JA TOISTO 40

    Toinen esimerkki:

    Ohjelma laskee asuntolainan kuukausierat.Anna lainasumma: 100000Anna laina-aika vuosina: 0Liian lyhyt laina-aika

    Sama ohjelma voidaan kirjoittaa for-kskyn avulla seuraavasti:

    def main():print("Ohjelma laskee asuntolainan kuukausierat.")rivi = input("Anna lainasumma: ")lainasumma = float(rivi)rivi = input("Anna laina-aika vuosina: ")laina_aika = int(rivi)if laina_aika < 1:

    print("Liian lyhyt laina-aika")else:

    kk_lkm = 12 * laina_aikarivi = input("Anna korkoprosentti: ")korko = float(rivi)lyhennys = lainasumma / kk_lkmpaaoma = lainasummaprint(" lyhennys korko yhteensa")for i in range(1, kk_lkm + 1):

    korkoera = korko / 1200.0 * paaomapaaoma = paaoma - lyhennyskuukausiera = korkoera + lyhennysprint("{:2d}. {:8.2f} {:8.2f} {:8.2f}".format(

    i, lyhennys, korkoera, kuukausiera))

    main()

    Tss ohjelmassa silmukkalaskuria i ei siis alusteta eik sen arvoa kasvateta jokakierroksella, koska for-ksky huolehtii nist toimenpiteist yhdess range-funktionkanssa.

  • Luku 4

    Funktiot

    Todellisessa elmss tarvittavat ohjelmat ovat usein thn asti esitettyj ohjelmiaselvsti pitempi, usein tuhansien ja jopa kymmenien tuhansien rivien pituisia. Oh-jelman rakenteen selkeyttmiseksi ohjelma jaetaan tllin pienempiin osiin, funk-tioihin. Funktio on ohjelman osa, jolle on annettu oma nimi. Tyypillisesti funktiosuorittaa jonkin tehtvn.

    Kun halutaan, ett funktio suoritetaan, kirjoitetaan ohjelmaan ksky, joka kutsuufunktiota. Funktion kutsu voi olla joko pohjelmassa tai sitten toisen funktionsisll.

    4.1 Yksinkertaisia esimerkkej

    Tarkastellaan seuraavaa esimerkki: halutaan kirjoittaa ohjelma, joka tulostaa ku-varuudulle alla olevan mallin mukaisen kuvion.

    ****

    *********

    *********

    *****

    Havaitaan, ett kuvio muodostuu kolmesta kolmiosta. Ohjelma voidaan kirjoittaanyt niin, ett kirjoitetaan funktio tulosta_kolmio, joka tulostaa yhden kolmion jasuoritetaan tm funktio kolme kertaa. Funktio mritelln samaan tapaan kuinpohjelmakin. Mrittely aloitetaan sanalla def ja funktion nimell, jonka jlkeentulevat sulut ja kaksoispiste. Seuraavalta rivilt alkavat sitten funktioon kuuluvatkskyt. Jlleen sisennysten avulla osoitetaan, mitk kskyt kuuluvat tmn funktionsislle.

    Pohjelman tehtvksi j kutsua funktiota tulosta_kolmio kolme kertaa. Funk-tiota kutsutaan kirjoittamalla sen nimi ja nimen pern sulut. Funktion kutsu saa

    41

  • LUKU 4. FUNKTIOT 42

    aikaan sen, ett pohjelman suoritus tavallaan keskeytetn ja siirrytn suoritta-maan funktioon kuuluvia kskyj. Kun funktio suoritus pttyy, siirrytn takaisinpohjelmaan ja jatketaan siit kohdasta, jossa pohjelman suoritus keskeytyi.

    Ohjelma on kokonaisuudessaan seuraava:

    def tulosta_kolmio():print(" * ")print(" *** ")print("*****")

    def main():tulosta_kolmio()tulosta_kolmio()tulosta_kolmio()

    main()

    Ohjelma tulostaa edell esitetyn kuvion. Koska pohjelmassa suoritetaan sama ks-ky (funktion tulosta_kolmio kutsu) kolme kertaa perkkin, voidaan kutsu kirjoit-taa mys toistokskyn sisn. Jos viel kutsukertojen mr mritelln vakioksi,on sit helppo muuttaa myhemmin. Muutettu pohjelma on seuraavan nkinen:

    def main():KERRAT = 3for i in range(KERRAT):

    tulosta_kolmio()

    Ohjelman muut osat jvt ennalleen. Toistokskyn sisll oleva ksky (funktiontulosta_kolmio kutsu) ei riipu mitenkn toistokskyss kytetyst muuttuj