Lista olion kenttänä
Olion kenttien ei tarvitse olla pelkästään lukuja ja merkkijonoja, vaan
kenttänä voi olla esimerkiksi lista tai jokin muu oliomuuttuja.
Tarkastellaan seuraavaksi esimerkkiä, jossa halutaan tehdä ohjelma
kaupan kanta-asiakasrekisterin hallintaan. Kirjoitetaan luokka
Bonusasiakas
yhden kanta-asiakkaan kuvaamiseen. (Varsinaista
rekisteriohjelmaa ei ole esitetty tässä materiaalissa.)
Luokan oliolla on kenttä asiakkaan nimeä varten sekä toinen kenttä
__ostokset
. Jälkimmäinen kenttä on lista, joka sisältää asiakkaan
tarkasteltavana ajanjaksona tekemien kertaostosten arvot.
Metodissa __init__
annetaan parametrin mukainen alkuarvo asiakkaan
nimelle ja luodaan tyhjä lista, joka asetetaan __ostokset
-kentän
arvoksi.
Metodi lisaa_ostos
lisää __ostokset
-listaan yhden uuden
ostoksen. Käytännössä se lisää listan loppuun uuden alkion, jonka arvo
annetaan metodin parametrina. Parametrin pitää kuitenkin olla
positiivinen. Jos parametrina annettu arvo on negatiivinen tai nolla,
ostosta ei lisätä listaan lainkaan. Metodi palauttaa arvon True
tai
False
sen mukaan, onnistuiko ostoksen lisääminen (parametri
sallitulla välillä) vai ei. Tätä tapaa voi yleisemminkin käyttää, kun
pitää välittää tieto metodin
suorituksen onnistumisesta ohjelman siihen kohtaan, jossa
metodia kutsutaan.
Metodi laske_keskiarvo
laskee asiakkaan tekemien ostosten keskiarvon
ja palauttaa sen. Jos asiakkaalla ei ole lainkaan ostoksia (lista
__ostokset
on tyhjä), metodi palauttaa arvon 0.0.
Metodi laske_rajan_ylittaneet
käy läpi listan __ostokset
ja
laskee, kuinka moni siinä olevista ostoksista ylittää parametrina
annetun rajan. Kauppa voi käyttää tätä metodia silloin, kun se haluaa
etsiä asiakkaita, jotka tekevät paljon suuria kertaostoksia.
Metodi laske_bonus
laskee ja palauttaa asiakkaalle tarkasteltavan
ajanjakson aikana kertyneen bonuksen.
Metodi nollaa_ostokset
tyhjentää asiakkaan __ostokset
-listan.
Tarkasti ottaen metodi luo uuden, tyhjän listan, ja panee
__ostokset
-kentän viittaamaan siihen. Tätä metodia on tarkoitus
käyttää tarkasteltavan aikajakson lopussa sen jälkeen, kun asiakkaan
bonukset on laskettu ja ostotiedot halutaan nollata seuraavaa aikajaksoa
varten.
Metodi __str__
on kirjoitettu niin, että se lisää palauttamaansa
merkkijonoon asiakkaan nimen ja ostokset, kunkin ostoksen omalle
rivilleen. Rivinvaihdot saadaan aikaan lisäämällä merkkijonoon
"\n"
-merkkejä. Ostosten arvot saadaan merkkijonoon kahden
desimaalin tarkkuudella käyttämällä f-stringejä.
Seuraavaksi koko luokan koodi:
# Luokka eraan kaupan yhden kanta-asiakkaan kuvaamiseen.
class Bonusasiakas:
# Metodi luo uuden bonusasiakkaan. Luotavan asiakkaan nimi
# annetaan metodin parametrina.
def __init__(self, asiakkaan_nimi):
self.__nimi = asiakkaan_nimi
self.__ostokset = []
# Metodi palauttaa bonusasiakkaan nimen.
def kerro_nimi(self):
return self.__nimi
# Metodi lisaa bonusasiakkalle yhden kertaostoksen. Ostoksen
# arvo annetaan metodin parametrina. Metodi palauttaa arvon
# True, jos ostos voidaan lisata, ja muuten arvon False.
def lisaa_ostos(self, arvo):
if arvo > 0.0:
self.__ostokset.append(arvo)
return True
else:
return False
# Metodi laskee ja palauttaa bonusasiakkaan kertaostosten
# keskiarvon.
def laske_keskiarvo(self):
lkm = 0
summa = 0.0
for ostoksen_arvo in self.__ostokset:
summa += ostoksen_arvo
lkm += 1
if lkm == 0:
return 0.0
else:
return summa / lkm
# Metodi laskee, kuinka moni bonusasiakkaan kertaostoksista
# ylittaa arvoltaan parametrina annetun rajan. Metodi palauttaa
# naiden kertaostosten lukumaaran.
def laske_rajan_ylittaneet(self, alaraja):
ylittaneiden_lkm = 0
for arvo in self.__ostokset:
if arvo > alaraja:
ylittaneiden_lkm += 1
return ylittaneiden_lkm
# Metodi laskee ja palauttaa asiakkaalle tulevan
# bonuksen, joka maaraytyy ostosten kokonaisarvon perusteella.
def laske_bonus(self):
PIENIBONUS = 1.0
SUURIBONUS = 2.5
BONUSRAJA = 400.0
summa = 0.0
for ostos in self.__ostokset:
summa += ostos
if summa >= BONUSRAJA:
bonus = SUURIBONUS * summa / 100.0
else:
bonus = PIENIBONUS * summa / 100.0
return bonus
# Metodi nollaa bonusasiakkaan ostostiedot.
def nollaa_ostokset(self):
self.__ostokset = []
# Metodi palauttaa merkkijonon, joka sisaltaa asiakkaan
# nimen ja ostokset, kunkin kertaostoksen arvon omalla rivillaan.
def __str__(self):
mjono = "Asiakas: " + self.__nimi + "\nOstot:\n"
for arvo in self.__ostokset:
mjono += f"{arvo:.2f} eur\n"
return mjono
Seuraavaksi esitetään esimerkki pääohjelmasta, joka luo kaksi
Bonusasiakas
-oliota ja suorittaa näille erilaisia toimenpiteitä.
Ohjelmassa on jälleen laadittu apufunktio desimaaliluvun lukemiseen
käyttäjältä. Ohjelma kannattaisi jakaa useampaan funktioon, mutta se on
tässä jätetty tekemättä, jotta olioiden luonti ja niiden metodien
kutsuminen olisi mahdollisimman selkeätä myös aloittelijalle.
Esimerkistä nähdään myös se, miten metodin lisaa_ostos
paluuarvoa
voidaan käyttää hyväksi. Koska metodi palauttaa arvon True
tai
False
, voidaan sen kutsu kirjoittaa suoraan if-käskyn ehdoksi.
Metodin kutsu if-käskyn ehtona saa aikaan metodin suorittamisen.
Lisäksi metodin paluuarvoa käytetään saman tien ratkaisemaan,
suoritetaanko if-käskyn sisällä oleva käsky.
import bonusasiakas
def lue_desimaaliluku():
luku_onnistui = False
while not luku_onnistui:
try:
luku = float(input())
luku_onnistui = True
except ValueError:
print("Virheellinen desimaaliluku!")
print("Anna uusi!")
return luku
def main():
OSTOSKERRAT = 4
nimi1 = input("Anna 1. asiakkaan nimi: ")
asiakas1 = bonusasiakas.Bonusasiakas(nimi1)
nimi2 = input("Anna 2. asiakkaan nimi: ")
asiakas2 = bonusasiakas.Bonusasiakas(nimi2)
for i in range(OSTOSKERRAT):
print(f"Anna asiakkaan {asiakas1.kerro_nimi():s} yhden kertaoston arvo.")
luettu_arvo = lue_desimaaliluku()
if asiakas1.lisaa_ostos(luettu_arvo):
print("Ostoksen lisays onnistui.")
else:
print("Ostoksen lisays ei onnistunut.")
for i in range(OSTOSKERRAT):
print(f"Anna asiakkaan {asiakas2.kerro_nimi():s} yhden kertaoston arvo.")
luettu_arvo = lue_desimaaliluku()
if asiakas2.lisaa_ostos(luettu_arvo):
print("Ostoksen lisays onnistui.")
else:
print("Ostoksen lisays ei onnistunut.")
print(f"1. asiakkaan ostosten keskiarvo: {asiakas1.laske_keskiarvo():.2f} eur")
print(f"2. asiakkaan ostosten keskiarvo: {asiakas2.laske_keskiarvo():.2f} eur")
print(f"1. asiakkaan bonus: {asiakas1.laske_bonus():.2f} eur")
print(f"2. asiakkaan bonus: {asiakas2.laske_bonus():.2f} eur")
print("Anna raja, jonka ylittavat ostokset haetaan.")
raja = lue_desimaaliluku()
ylitykset1 = asiakas1.laske_rajan_ylittaneet(raja)
ylitykset2 = asiakas2.laske_rajan_ylittaneet(raja)
print(f"1. asiakkaalla oli {ylitykset1:d} suurempaa ostosta")
print(f"2. asiakkaalla oli {ylitykset2:d} suurempaa ostosta")
print("Asiakkaiden tiedot:")
print(asiakas1)
print(asiakas2)
asiakas1.nollaa_ostokset()
print("1. asiakas nollauksen jalkeen:")
print(asiakas1)
main()
Alla on esimerkki ohjelman suorituksesta:
Anna 1. asiakkaan nimi: Anna Lahti
Anna 2. asiakkaan nimi: Roope Rikas
Anna asiakkaan Anna Lahti yhden kertaoston arvo.
45.0
Ostoksen lisays onnistui.
Anna asiakkaan Anna Lahti yhden kertaoston arvo.
-12.8
Ostoksen lisays ei onnistunut.
Anna asiakkaan Anna Lahti yhden kertaoston arvo.
0.0
Ostoksen lisays ei onnistunut.
Anna asiakkaan Anna Lahti yhden kertaoston arvo.
15.0
Ostoksen lisays onnistui.
Anna asiakkaan Roope Rikas yhden kertaoston arvo.
120.0
Ostoksen lisays onnistui.
Anna asiakkaan Roope Rikas yhden kertaoston arvo.
10.30
Ostoksen lisays onnistui.
Anna asiakkaan Roope Rikas yhden kertaoston arvo.
120.4
Ostoksen lisays onnistui.
Anna asiakkaan Roope Rikas yhden kertaoston arvo.
180.0
Ostoksen lisays onnistui.
1. asiakkaan ostosten keskiarvo: 30.00 eur
2. asiakkaan ostosten keskiarvo: 107.68 eur
1. asiakkaan bonus: 0.60 eur
2. asiakkaan bonus: 10.77 eur
Anna raja, jonka ylittavat ostokset haetaan.
44.0
1. asiakkaalla oli 1 suurempaa ostosta
2. asiakkaalla oli 3 suurempaa ostosta
Asiakkaiden tiedot:
Asiakas: Anna Lahti
Ostot:
45.00 eur
15.00 eur
Asiakas: Roope Rikas
Ostot:
120.00 eur
10.30 eur
120.40 eur
180.00 eur
1. asiakas nollauksen jalkeen:
Asiakas: Anna Lahti
Ostot: