Sisällysluettelo

Python esimerkkejä


/ Heikin pohteita/ Ohjelmointia, matematiikkaa, fysiikkaa … Python esimerkkejä /Python esimerkkejä

 

Python esimerkkejä

Tutustumme aluksi muutamaan pieneen esimerkkiohjelmaan. Pikaisella vilkaisulla ohjelmoinnin aloittelija ei saane selvää, miten ne toimivat, mutta kohtuullisella ponnistelulla ja kokeilulla ne opettavat paljon ohjelmoinnista.

 

Esimerkki: Fibonnacin luvut

Jos olet kiinnostunut matematiikasta ja tiedät, mitä ovat fibonnacin luvut sinua saattaa hetken säväyttää seuraava ohjelma. Ellet tunne fibonnacin lukuja, harjoitus tuntunee tyhmältä, mutta tee se silti.

# Määritellään funktio fib(n), jolla on yksi argumentti, n
def fib(n):
    if n == 0:    # Jos n on yhtäsuuri kuin nolla,
        return 0  # funktio saa arvon 0
    elif n == 1:  # muuten, jos n on yhtäsuuri kuin 1
        return 1  # funktio saa arvon 1
    else:         # muissa tapauksissa funktio saa arvokseen
        return fib(n-1) + fib(n-2)  # kahden edeltävän fibonnacin luvun summan

# Pääohjelma
print(fib(5))

Python-kielisestä funktiosta fib(n) saattaa tunnistaa fibonnacin luvun määritelmän, vaikka merkintätapa onkin eri kuin matematiikan kirjoissa.

Käynnistä spyder, kopio ylläoleva sen editointi-ikkunaan allaolevan kuvan mukaisesti ja tallenna tiedostoon fibonnacci.py. Suorita ohjelma painamalla F5. Samall F5-painallus tuo ohjelmamodulin funktion järjestelmän tietoon niin, että voit kutsua sitä myös konsolilta — kirjoittamalla esimerkiksi fib(12) kuvan mukaisesti spyder-ohjelmointiympäristön oikeassa alalaidassa olevan konsoli-ikkunan komentoriville. (Ilman F5-painallusta saat funktion konsolilta kutsuttavaksi kirjoittamalla konsolille from fibonnacci import fib.)

../xml/Programming/PythonOpetus/spyder_figs/spyder_fibo.png
 

Yleensä tietokone suorittaa kirjoittamasi ohjelman silmänräpäyksessä, mutta jos innostuit kokeilemaan jonkin ison fibonnacin luvun laskemista, kyllästyit kenties odottelemaan vastausta. Spyderin konsoli-ikkunan oikeassa yläkulmassa on punainen neliö, josta ohjelman voi pysäyttää, mikäli se tuntuu jääneen "jumiin".

Yleensä ohjelma jää "jumiin" ohjelmointivirheen takia, mutta nyt "jumittuminen" johtuu siitä, että fibonnacin luvun määrittäminen on monimutkainen laskutehtävä. 35:tä suuremmat fibonnacci luvut osoittautuivat minun koneellani niin hitaiksi laskea, etten jaksanut odottaa tulosta.

Hakukoneile "fibonnacci complexity" jos sinua jäi mietityttämään, miksi noin pienen muutaman rivin funktion arvon laskeminen voi olla liikaa tehokkaalle tietokoneelle.


 

Pieniä Python-kielisiä esimerkkejä

Ei kannata pelästyä, vaikka seuraavat ohjelmanpätkät näyttävät vaikeaselkoisilta. Ohjelmointia tuntemattomalle ohjelmakoodi näyttänee täysin käsittämättömältä. Myös ohjelmointia tuntevan on usein vaikea saada selvää toisen kirjoittamasta ohjelmasta. Vasta harjaantunut ohjelmoija, joka tuntee käytettävän ohjelmointikielen, voi lukea jonkun muun tekemää ohjelmaa ilman suurempia vaikeuksia.

Python--ohjelmaa lukiessa on hyvä tietää, että rivien sisennys määrää, mihin ylempään kokonaisuuteen rivi kuuluu. Aivan vasemmasta laidasta alkavat rivit kuuluvat ohjelman päätasolle. Yllä funktio fib(n) määriteltiin siis päätasolle, koska def fib(n): alkaa rivin alusta. Sitä seuraavat sisennetyt rivit kuuluvat funktion määrittelyyn — ne kertovat, mitä funktio tekee.

Seuraavaa esimerkkiä ei kannata yrittää ymmärtää yhdellä vilkaisulla. Lataa allaolevan ohjelman koodi kehitysympäristöön ja kokeile kuten yllä fibonnaccin lukuja laskevaa funktiota.

Mikäli et ole installoinut pylab-modulia, laita kommentiksi rivit, joissa viitataan pylabiin. Eli laita kyseisten rivien alkuun #-merkki. Voit myös yrittää installoida pylab-modulin komennolla pip install pylab tai jos käytät Python3:a komennollapip3 install pylab. Jos se aiheuttaa virheilmoituksia, jätä sikseen vähäksi aikaa. Emme tarvitse pylabia tästä eteenpäin.

# -*- coding: utf-8 -*-

import pylab

# lasketaan kokonaislukujen 1..k summa for-silmukan avulla
# tulostetaan joka kierroksella välitulos
# huom. Pythonin range(k) antaa luvut 0:sta (k-1):een.

def summa(k):
    s = 0
    for i in range(k+1):
        s = s+(i)
        print("i: ", i, "s: ", s)
    return s


# lasketaan kokonaiskukujen 1..k rekursiivisella funktiolla.
# Rekursiossa funktio kutsuu itseään, kunnes lopetusehto
# (tässä tapauksessa k == 0) toteutuu.
def summaR(k):
    print("summaR ", k)
    if k == 0:
        return 0
    return k+summaR(k-1)


# Esimerkkejä eri tavoista saada tulostettua jotain konsolille
def mjonot():
    s = "Tämä on merkkijono "
    m = 53
    print(s)
    print("luku ja merkkijono ", m, str(m))
    print("kaksi merkkijonoa yhdistetty + merkillä: ")
    print(s+str(m))
    m = 120
    n = 15
    print(m+n)
    print(str(m)+str(n))
    print(str(m)+' '+str(n))


# Esimerkki siitä, miten lukea konsolilta.
# Input tuottaa merkkijonon, joten muutamme sen int()-funktiolla
# kokonaisluvuksi
def kysymys():
    N = input("anna luku: ")
    print('luku on:', N, type(N))
    S = summa(int(N))
    print("lukujen 1..", N, " summa on: ", S)
    print("lukujen 1.."+str(N)+" summa on: "+str(S))


# piirretään funktion y = x**3 kuvaaja
# Muodostetaan listat/taulukot xx ja yy toisiaan vastaavilla
# x ja y arvoille.
# loppu hoituu pylab-funktioilla
# huom. Pythonin range(i,j) antaa luvut i:stä (j-1):een.

def kuvaaja():
    xx = [i for i in range(-10, 11)]
    yy = [i**3 for i in range(-10, 11)]

print("xx:")
print(xx)
print("yy:")
print(yy)

pylab.plot(xx, yy)
pylab.title('y = x**3')
pylab.ylabel("x**3")
pylab.xlabel("x")
pylab.savefig('y_x3.png')
pylab.show()

# Huom. Merkkijoissa \n aiheuttaa rivinvaihdon
print('\npääohjelma\n')

print("summa(5):")
s = summa(5)
print(s)
print("\nsummaR(5): ")
s = summaR(5)
print(s)

print("\nmerkkijonot")
mjonot()

kysymys()

print("\nkuvaaja:")
kuvaaja()

# voit kutsua funktiota konsolilta


Ylläolevan ohjelman koodi

Ohjelma kirjoittaa konsolille seuraavaa, kun painat F5:

pääohjelma

summa(5):
i:  0 s:  0
i:  1 s:  1
i:  2 s:  3
i:  3 s:  6
i:  4 s:  10
i:  5 s:  15
15

summaR(5):
summaR  5
summaR  4
summaR  3
summaR  2
summaR  1
summaR  0
15

merkkijonot
Tämä on merkkijono
luku ja merkkijono  53 53
kaksi merkkijonoa yhdistetty + merkillä:
Tämä on merkkijono 53
135
12015
120 15

anna luku: 4
luku on: 4 <class 'str'>
i:  0 s:  0
i:  1 s:  1
i:  2 s:  3
i:  3 s:  6
i:  4 s:  10
lukujen 1.. 4  summa on:  10
lukujen 1..4 summa on: 10

kuvaaja:
xx:
[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
yy:
[-1000, -729, -512, -343, -216, -125, -64, -27, -8, -1, 0, 1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

Ohjelman suorituksen lisäksi F5:näppäimen painaminen lataa ohjelman python järjestelmän työtilaan niin, että voit kutsua kutsua funktioita konsolilta. Esimerkiksi summa(3) laskee summan 0+1+2+3. Funktion koodin mukaisesti ensin asetetaan muuttujalle s arvo 0 ja sen jälkeen käydään foor-silmukassa läpi i:n arvot nollasta kolmeen ja joka kierroksella lisätään kukin i s:ään ja tulostetaan muuttujien arvot. Lopuksi funktio palauttaa s:n lopullisen arvon.

Ehkä ihmettelet for silmukassa käskyä range(k+1). Miksei range(k)? Kirjoita konsolin komentoriville range(3) niin saat listan [0,1,2]. Voit myös kirjoittaa range(1,3) niin saat listan [1,2]. Jostain syystä on nähty järkevästi, että range-käsky toimii noin.

Funtion summaR(k) näyttää, miten funktio voi kutsua itseään. Esimerkiksi lukujen yhdestä kolmeen summa on kolme plus lukujen yhdestä kahteen summa. Rekursiivisen funktion toimintaa voi olla vaikea hahmottaa, mutta yritä kuitenkin. Välitulostukset saattaavat auttaa.

Esimerkeissä tulostuksesta ja syötteiden lukemisesta konsolilta ei ole hirveästi ymmärrettävää. Ne esittelevät eri vaihtoehtoja. Esimerkkien komennot voi kopioida tarvittaessa omaan ohjelmaansa.

Lopuksi piirretään funktion

y = x 3
kuvaaja. Python-kielessä "x potenssiin kolme" merkitään x**3. Piirtämisessä käytetään pylab-nimisen modulin funktiota plot, jolle pitää antaa kaksi argumenttia — luettelo x:n arvoista ja luettelo niitä vastaavista y:n arvoista.

../xml/Programming/PythonOpetus/y_x3.png
 

 

Pythonin olioita

Seuraava — ei aivan yksinkertainen — esimerkki esittelee olio-ohjelmointia Pythonilla . Tämä opas olio-ohjelmointiin pythonilla kertoo lisää olio-ohjelmoinnista

Esimerkissä kauppiaat ostavat ja myyvät, mutta esimerkki ei kuitenkaan kuvasta todellista kaupankäyntiä. Siinä ei ole juuri muuta järkeä kuin, että siihen on upotettu olio-ohjelmoinnin perusteita.

# -*- coding: utf-8 -*-
"""
Created on Wed May 27 21:10:55 2015

@author: heikki
"""

# Määritellään, minkä tyyppisiä olioita ovat kauppiaat tässä ohjelmassa
# Kullakin kauppiaalle on ominaisuudet varasto, kassa, tavaran yksikköhinta
# ja nimi
class kauppias():
    def __init__(self, kpl, Eur, hinta, nimi):
    self.varasto = kpl
    self.kassa = Eur
    self.hinta = hinta
    self.nimi = nimi

# Kauppiaaseen liittyy metodi report, joka kertoo kauppiaan liiketoiminnan
# tilan
    def report(self):
    print(self.nimi, " Varasto:",
    self.varasto, "Kassa: ", self.kassa)

# Kauppiaalla on metodit osta ja myy
# kun myyn, varastoni pienenee ja kassaan tulee rahaa.
# Lisäksi kerron ostajalle ostoksen hinnan
    def myy(self, kpl):
        self.varasto -= kpl
        self.kassa += kpl*self.hinta
        return self.hinta*kpl

# Python-kielessä a = a+b ei ole yhtälö vaan tarkoittaa, että a:n uusi arvo on
# a:n vanha arvo lisättynä b:llä
# operaatio a += b on sama kuin a = a+b. Vastaavasti a -= b

# Kun ostan myyjältä, tämä kertoo ostokseni hinnan
# Kassani pienee ja varastoni kasvaa
    def osta(self, kpl, Myyja):
            maksu = Myyja.myy(kpl)
            self.kassa -= maksu
            self.varasto += kpl


# Pääohjelma (ohjelman suoritus) alkaa tästä.
# "Luodaan" kaksi kauppiasta, A ja B. (Kauppiaita voisi olla vaikka sata)
# Kauppias A: Varastoa 100 kpl, kassassa 100 euroa, myy hintaan 2€/kpl
A = kauppias(100, 100, 2, 'Jaska')

# Kauppias B: Varastoa 50 kpl, kassassa 200 euroa, myy hintaan 1€/kpl
B = kauppias(50, 200, 1, 'Kalle')

# Esimerkki siitä, miten kutsutaan olion metodia
print("\nAlkutilanteen raportoinnit")
A.report()
B.report()

print("\nA ostaa B:ltä 20 kpl B:n tarjoamaan edulliseen hintaan")
A.osta(20, B)
A.report()
B.report()

print("\nB ostaa A:lta 10 kpl A:n pyytämään kalliimpaan hintaan")
B.osta(10, A)
A.report()
B.report()


Ylläolevan ohjelman koodi

Ohjelma kirjoittaa konsolille seuraavaa, kun painat F5:

Alkutilanteen raportoinnit
Jaska  Varasto: 100 Kassa:  100
Kalle  Varasto: 50 Kassa:  200

A ostaa B:ltä 20 kpl B:n tarjoamaan edulliseen hintaan
Jaska  Varasto: 120 Kassa:  80
Kalle  Varasto: 30 Kassa:  220

B ostaa A:lta 10 kpl A:n pyytämään kalliimpaan hintaan
Jaska  Varasto: 110 Kassa:  100
Kalle  Varasto: 40 Kassa:  200


Ohjelman toimintaa lienee vaikea ymmärtää, mutta yritä silti. Aloita kohdasta "pääohjelma alkaa tästä". Aluksi luodaan kaksi oliota A ja B, jotka ovat tyyppiä kauppias. Voit ajatella, että olio on määrämuotoinen arkistokortti — muistilappu, jollainen tehdään jokaisesta kauppiaasta. Ylempänä ohjelmakoodissa määrittelyn class kauppias: sisällä funktion _init_ määrittely kertoo, mitä "arkistokorttiin" kirjoitetaan: Varaston määrä; kassan suuruus; yksikköhinta, jolla kauppias myy tavaroitaan sekä kauppiaan nimi.

Käskyllä A.report() pyydämme kauppiasta A kertomaan yrityksensä tilanne. Funktio report() on määritelty luokan (class) kauppias sisällä. (Luokan sisällä määriteltyjä funktioita kutsutaan olio-ohjelmoinnissa metodeiksi.) Vastaavasti käskyllä B.report() pyydämme samat tiedot kauppiaalta B.

Ei liene helppo ymmärtää, miksi käytetään termejä class, luokka, metodi,– – ja siksi termeissä menee helposti sekaisin. Paras ottaa mallia yksinkertaisesta esimerkistä ja näin aluksi unohtaa termien alkuperän pähkäily.

Käskyllä A.osta(20,B) pyydämme A:ta ostamaan B:ltä 20 kappaletta. Metodit osta ja myy päivittävät varastojen ja kassojen tilanteet vastaamaan uutta tilannetta. Koeta selvittää, miten se tapahtuu.

Voit yrittää luoda vielä kolmannen kauppiaan ja lisätä ostotapahtumia. Jos onnistut, sinulla ei enää ole kovin paljoa opittavaa olio-ohjelmoinnin periaatteista.


Esimerkkejä funktioiden käsittelystä ja piirtelystä