Objekt-orientert programmering - livekoding og oppgaver

Vi skal skrive et lite program for å administrere et lotteri der ulike personer kan kjøpe lodd, og det trekkes en vinner til slutt. Med alt vi har lært til nå (unntatt å skrive klasser), kan vi representere et lotteri slik:

# Liste over lodd og hvem som har kjøpt loddene
lotterilodd = ["Espen", "Marius", "Mari", "Emilie"]
# Premien
lotteripremie = 1000000
# Navn på lotteriet
lotterinavn = "Superjackpot"

# Funksjon som kalles når noen kjøper et nytt lodd. Merk at premien skal øke med 1000 kroner for hvert lodd
def legg_til_nytt_lodd(navn):
    lotteripremie += 1000
    lotterilodd.append(navn)

def trekk_vinner():
    print("Trekker vinner i", lotterinavn)
    vinner = random.choice(lotterilodd)
    print("Vinneren ble", vinner, ". Gratulerer, du vant ", lotteripremie, " kroner!")

def print_informasjon_om_lotteriet():
    print("Lotteriet", lotterinavn, " har en premie på ", lotteripremie, " kroner og det er kjøpt", len(lotterilodd) , " lodd.")

Merk at vi her lar alle variablene være globale, noe vi ikke anbefaler. Denne løsningen vil for eksempel fungere dårlig hvis vi ønsker å ha to lotterier og ikke bare ett. Si for eksempel at vi har to lotterier som vi definerer med to sett med variable:

lotterilodd1 = ["Espen", "Marius", "Mari", "Emilie"]
lotteripremie1 = 1000000
lotterinavn1 = "Superjackpot"

lotterilodd2 = ["Mari", "Mari", "Mari", "Emilie"]
lotteripremie2 = 1000
lotterinavn2 = "Superjackpot nr. 2"

Funksjonene som tar globale variable må ha "harkodet" variabelnavn, og vil ikke kunne trekke vinner i begge lotteriene.

Men dette kan løses ved å la funksjonene ta parametere i stedet:

def legg_til_nytt_lodd(lotterilodd, lotteripremie, loddeier):
    lotterilodd.append(loddeier)
    lotteripremie += 1000

Alle funksjonene våre (tre funksjoner i dette tilfellet) vil da måtte ta parameterene som brukes. Dette blir fort litt tungvint, spesielt hvis man har mange funksjoner og mange parametere.

En måte å forenkle ting litt på kan være å gruppere variablene i en ordbok:

lotteri1 = {"navn": "Superjackpot", "lodd": ["Espen", "Marius", "Mari", "Emilie"], "premie": 1000000}
lotteri2 = {"navn": "Superjackpot nr. 2", "lodd": ["Mari", "Mari", Mari", "Emilie"], "premie": 1000}

Funksjonene trenger da bare ta ett parameter:

def print_informasjon_om_lotteriet(lotteri):
    print("Lotteriet", lotteri["navn"], " har en premie på ", lotteri["premie"], " kroner og det er kjøpt", len(lotteri["lodd"]) , " lodd.")

# osv ...

En ordbok er én måte å gruppere ulik data sammen i én variabel på. Å lage et objekt er en annen måte. Vi har lært at vi kan lage våre egne objekter slik:

class Lotteri:
    def __init__(self, lodd, premie, navn):
        self.lodd = lodd
        self.premie = premie
        self.navn = navn 

lotteri = Lotteri(["Mari", "Emilie"], 1000000, "Superjackpot")

lotteri er nå et objekt, og vi kan sende det objektet i stedet for ordboken vår inn i funksjonene våre:

def print_informasjon_om_lotteriet(lotteri):
    print("Lotteriet", lotteri.navn, " har en premie på ", lotteri.premie, " kroner og det er kjøpt", len(lotteri.lodd) , " lodd.")

Vi kan altså definere funksjoner som tar objekt som parameter. En slik løsning blir veldig lik som å sende en ordbok inn som parameter.

Men her har Python et triks som kan gjøre ting enda mer elegant og enklere for oss. Objekter kan nemlig ha egne funksjoner (såkalte metoder) som automatisk har tilgang til alle variablene som er knyttet til objektet. Disse funksjonene kan altså operere på objektet selv:

class Lotteri:
    def __init__(self, lodd, premie, navn):
        self.lodd = lodd
        self.premie = premie
        self.navn = navn 

    # Her definerer vi en metode. Første parameter er alltid self, og via self får vi tilgang til alle variablene i objektet
    def print_informasjon_om_lotteriet(self):
        print("Lotteriet", self.navn, " har en premie på ", self.premie, " kroner og det er kjøpt", len(self.lodd) , " lodd.")

Oppgave 1

Legg til de to andre metodene i klassen, trekk_vinner og legg_til_nytt_lodd.

Oppgave 2 (ekstraoppgave)

Lag en metode som endrer navn på lotteriet og en metode som endrer premien til lotteriet.