Listan alkiona olioita

Palataan luvun alun esimerkkiin, jossa haluttiin käsitellä ohjelmointikurssin opiskelijatietoja. Opiskelijoita on sen verran monta, että ei ole järkevää määritellä omaa muuttujaa jokaista luotavaa Opiskelija-oliota varten. Sen sijaan luodut Opiskelija-oliot (tai täsmällisesti ottaen viitteet luotuihin olioihin) voidaan tallentaa listaan. Kun lista on luotu, sen loppuun voidaan lisätä uusi Opiskelija-olio esimerkiksi seuraavasti:

opiskelijalista.append(Opiskelija("Matti Virtanen", "11111F"))

Tässä on siis sekä luotu uusi olio että lisätty se heti listan loppuun. Toinen vaihtoehto on luoda ensin olio, panna jokin muuttuja viittaamaan siihen ja lisätä sitten olio listaan tämän muuttujan avulla:

uusi_opiskelija = Opiskelija("Matti Virtanen", "11111F")
opiskelijalista.append(uusi_opiskelija)

Listaa voidaan indeksoida samalla tavalla kuin lukuja sisältävää listaa. Jos lista jo sisältää vähintään i + 1 alkiota, voidaan sen indeksille i sijoittaa viittaus juuri luotuun Opiskelija-olioon esimerkiksi seuraavasti (listassa indeksillä aikaisemmin ollut arvo häviää):

uusi_opiskelija = Opiskelija("Matti Virtanen", "11111F")
opiskelijalista[i] = uusi_opiskelija

Listassa indeksillä i olevalle Opiskelija-oliolle voidaan kutsua Opiskelija-luokan metodeita seuraavasti:

print("Opiskelijan", opiskelijalista[i].kerro_nimi())
print("kurssiarvosana on", opiskelijalista[i].laske_kokonaisarvosana())

On myös mahdollista käydä for-käskyssä läpi kaikki listan oliot ja kutsua heille jokaiselle vuorotellen luokan metodeita seuraavaan tapaan:

for kurssilainen in opiskelijalista:
    print("Opiskelijan", kurssilainen.kerro_nimi())
    print("kurssiarvosana on", kurssilainen.laske_kokonaisarvosana())

Katsotaan sitten esimerkkiohjelmaa, joka ensin lukee käyttäjän antamat opiskelijoiden nimet ja opiskelijanumerot, pyytää sen jälkeen käyttäjältä samojen opiskelijoiden tentti- ja harjoitusarvosanat ja lopuksi tulostaa tuloslistan, jossa on myös opiskelijoiden kokonaisarvosanat.

Tämä ohjelma on jaettu useampaan funktioon, ja tieto Opiskelija-oliot sisältävästä listasta välitetään funktioiden välillä funktioiden parametrien ja paluuarvojen avulla.

Funktio lue_kokonaisluku on jälleen apufunktio, joka lukee käyttäjältä yhden kokonaisluvun ja käsittelee mahdolliset virheelliset syötteet.

Funktio lue_opiskelijatiedot luo ensin tyhjän listan opiskelijoita varten. Sitten se lukee opiskelijoiden nimet ja opiskelijanumerot käyttäjältä niin, että yhden opiskelijan nimi ja opiskelijanumero on annettu yhdellä rivillä. Tästä rivistä erotetaan split-metodin avulla erikseen nimi ja opiskelijanumero. Näiden perusteella luodaan uusi Opiskelija-olio ja lisätään se listan loppuun. Kun kaikkien opiskelijoiden tiedot on luettu, funktio palauttaa arvonaan opiskelijat sisältävän listan.

Funktio lisaa_arvosanatiedot käy parametrina annetun Opiskelija-olioita sisältävän listan läpi olio kerrallaan. Se pyytää käyttäjältä kunkin opiskelijan tentti- ja harjoitustehtäväarvosanan ja antaa ne käsiteltävälle oliolle Opiskelija-luokan metodien avulla.

Funktio tulosta_tulokset käy jälleen parametrina annetun Opiskelija-olioita sisältävän listan läpi. Se tulostaa jokaisesta opiskelijasta opiskelijanumeron, nimen sekä tentti-, harjoitus- ja kokonaisarvosanan, jotka selvitetään Opiskelija-luokan metodien avulla. Listan läpi käyvä for-käsky on nyt kirjoitettu vähän eri muotoon kuin edellisessä funktiossa. Tämä ei ole mitenkään välttämätöntä, vaan for-käsky olisi voitu kirjoittaa myös samalla tavalla kuin funktiossa lue_arvosanatiedot. Esimerkissä on vain haluttu näyttää, miten listaa voi käydä läpi myös indeksoinnin avulla.

Pääohjelma kutsuu määriteltyjä funktioita niin, että halutut toimenpiteet (opiskelijoiden henkilötietojen kysyminen, arvosanatietojen kysyminen ja tulosten tulostaminen) tehdään halutussa järjestyksessä. Tulostamisessa yksi tulosrivi on koottu useasta f-stringien avulla muotoilusta merkkijonosta.

import opiskelija

def lue_kokonaisluku():
    luku_onnistui = False
    while not luku_onnistui:
        try:
            luku = int(input())
            luku_onnistui = True
        except ValueError:
            print("Virheellinen kokonaisluku!")
            print("Anna uusi!")
    return luku


# Funktio lukee kayttajien antamien opiskelijoiden nimet ja
# opiskelijanumerot. Se luo vastaavat Opiskelija-oliot ja
# lisaa ne listaan. Funktio palauttaa taman listan.

def lue_opiskelijatiedot():
    opiskelijat = []
    print("Anna opiskelijoiden nimet ja opiskelijanumerot")
    print("samalla rivilla kauttaviivalla erotettuna.")
    print("Lopeta tyhjalla rivilla.")
    rivi = input()
    while rivi != "":
        tiedot = rivi.split("/")
        if len(tiedot) != 2:
            print("Virheellinen rivi!")
        else:
            uusi = opiskelija.Opiskelija(tiedot[0], tiedot[1])
            opiskelijat.append(uusi)
        rivi = input()
    print("Opiskelijoiden tiedot luettu!")
    return opiskelijat


# Funktio pyytaa kayttajalta parametrina saadussa listassa
# olevien opiskelijoiden tentti- ja harjoitusarvosanat ja
# lisaa ne listan Opiskelija-olioille.

def lisaa_arvosanatiedot(opiskelijalista):
    for kurssilainen in opiskelijalista:
        print(f"Anna opiskelijan {kurssilainen.kerro_nimi():s} tenttiarvosana:")
        tentti_as = lue_kokonaisluku()
        print("harjoitusarvosana:")
        harjoitus_as = lue_kokonaisluku()
        kurssilainen.muuta_tenttiarvosana(tentti_as)
        kurssilainen.muuta_harjoitusarvosana(harjoitus_as)
    print("Arvosanat lisatty!")


# Funktio tulostaa parametrina annetussa listassa
# olevien Opiskelija-olioiden kurssitulokset.

def tulosta_tulokset(opiskelijat):
    print("numero nimi            tentti harj   kurssi")
    for i in range(len(opiskelijat)):
        print(f"{opiskelijat[i].kerro_opiskelijanumero():6s} " +
              f"{opiskelijat[i].kerro_nimi():15s} " +
              f"{opiskelijat[i].kerro_tenttiarvosana():<6d} " +
              f"{opiskelijat[i].kerro_harjoitusarvosana():<6d} " +
              f"{opiskelijat[i].laske_kokonaisarvosana():<6d}")


def main():
    opiskelijatiedot = lue_opiskelijatiedot()
    lisaa_arvosanatiedot(opiskelijatiedot)
    tulosta_tulokset(opiskelijatiedot)
    print("Ohjelma paattyy.")


main()

Alla on esimerkki ohjelman suorituksesta:

Anna opiskelijoiden nimet ja opiskelijanumerot
samalla rivilla kauttaviivalla erotettuna.
Lopeta tyhjalla rivilla.
Virta Nina/66445G
Heikkila Heikki/77553V
Lahti Mika/56789T
Lahti Maija/87642R

Opiskelijoiden tiedot luettu!
Anna opiskelijan Virta Nina tenttiarvosana:
4
harjoitusarvosana:
5
Anna opiskelijan Heikkila Heikki tenttiarvosana:
5
harjoitusarvosana:
5
Anna opiskelijan Lahti Mika tenttiarvosana:
1
harjoitusarvosana:
3
Anna opiskelijan Lahti Maija tenttiarvosana:
5
harjoitusarvosana:
0
Arvosanat lisatty!
numero nimi            tentti harj   kurssi
66445G Virta Nina      4      5      5
77553V Heikkila Heikki 5      5      5
56789T Lahti Mika      1      3      2
87642R Lahti Maija     5      0      0
Ohjelma paattyy.