6. Klasser

Programmeringsteknik

(Skillnad mellan versioner)
Hoppa till: navigering, sök
(Metoder)
Nuvarande version (21 juli 2015 kl. 17.01) (redigera) (ogör)
 
(32 mellanliggande versioner visas inte.)
Rad 1: Rad 1:
 +
{| border="0" cellspacing="0" cellpadding="0" height="30" width="100%"
 +
| style="border-bottom:1px solid #797979" width="5px" |  
 +
{{Mall:Vald flik|[[6. Klasser|Teori]]}}
 +
{{Mall:Ej vald flik|[[6. Övningar|Övningar]]}}
 +
{{Mall:Ej vald flik|[[6. Exempel|Exempel1]]}}
 +
{{Mall:Ej vald flik|[[6. Exempel2|Exempel2]]}}
 +
{{Mall:Ej vald flik|[[6. Inlämningsuppgift 3|Inlämningsuppgift 3: Nöjesfält]]}}
 +
| style="border-bottom:1px solid #797979" width="100%"|  
 +
|}
 +
 +
==Objektorientering==
==Objektorientering==
Rad 15: Rad 26:
för rymdskepp kan vi sedan skapa hur många rymdskepps-objekt vi vill!
för rymdskepp kan vi sedan skapa hur många rymdskepps-objekt vi vill!
-
'''Fråga: Vi vill skriva ett program för att lägga patiens. Vilken av följande klasser ska vi definiera i programmet?'''
+
[[Bild:Husdjursobjekt.jpg|frame|right]]
-
# Poäng
+
-
# Spader
+
-
# Kort
+
-
'''Svar:'''<span style="color:white">Klassen Kort, så att vi kan skapa många kort-objekt som kan användas i patiensen. </span>
+
-
 
+
Det stora exemplet i det här avsnittet kommer att handla om ett virtuellt
Det stora exemplet i det här avsnittet kommer att handla om ett virtuellt
husdjur. Ett husdjur kan ju ha många egenskaper, men vi väljer ut två att
husdjur. Ett husdjur kan ju ha många egenskaper, men vi väljer ut två att
Rad 27: Rad 33:
skick ska påverkas av hur den behandlas.
skick ska påverkas av hur den behandlas.
-
==Attribut==
+
===Attribut===
De variabler som används för att lagra data som hör till objektet
De variabler som används för att lagra data som hör till objektet
Rad 44: Rad 50:
Med ''self'' menar man objektet självt.
Med ''self'' menar man objektet självt.
-
 
+
===Metoder===
-
'''Fråga: Anta att vi jobbar med ett program för vitvaruhandeln. Vilka av följande alternativ skulle passa som attribut för ett spis-objekt?'''
+
-
[[Bild:Spis.jpg|Gammal spis|right]]
+
-
# bredd
+
-
# energiklass
+
-
# ugnsvolym
+
-
'''Svar:'''<span style="color:white">Alla alternativen skulle passa bra som attribut! </span>
+
-
 
+
-
==Metoder==
+
Funktionerna som hör till ett objekt kallas ''metoder''. För att en
Funktionerna som hör till ett objekt kallas ''metoder''. För att en
Rad 65: Rad 63:
<pre>
<pre>
def banna(self):
def banna(self):
-
print
+
print()
-
print "- Fy på dig", self.namn, "!"
+
print("- Fy på dig", self.namn, "!")
self.skick -= 3
self.skick -= 3
</pre>
</pre>
Rad 83: Rad 81:
<br clear="all" />
<br clear="all" />
-
'''Fråga: I en internetbutik vill vi ha ett objekt som representerar en kundvagn. Vilka av följande kan tänkas bli metoder i ett kundvagns-objekt?'''
 
-
# lägga ner en vara i kundvagnen
 
-
# beräkna totalpriset för alla varor i kundvagnen
 
-
# räkna ut dagens vinst för internetbutiken
 
-
'''Svar:'''<span style="color:white">Alla utom sista alternativet - det hör
 
-
inte till själva kundvagnen.</span>
 
-
==Konstruktorn==
+
===Speciella metoder: konstruktorn och str===
 +
 
 +
Metoder får man döpa precis som man vill. Men
 +
det finns ett par metodnamn som har speciell betydelse för Python.
 +
Här tar vi upp två av dessa. Metodnamnen börjar och slutar med
 +
två understrykningstecken, så det finns ingen risk att man råkar
 +
välja namnen av misstag.
''Konstruktorn'' är en speciell metod som man skriver för att ''initiera''
''Konstruktorn'' är en speciell metod som man skriver för att ''initiera''
objekt, dvs ge objektets attribut de värden de ska ha från början.
objekt, dvs ge objektets attribut de värden de ska ha från början.
Konstruktorn anropas automatiskt varje gång ett objekt skapas.
Konstruktorn anropas automatiskt varje gång ett objekt skapas.
-
I Python måste man döpa sin konstruktor till __init__ (alltså init
+
I Python måste man döpa sin konstruktor till <code>__init__</code> (alltså init
med två understrykningstecken både före och efter).
med två understrykningstecken både före och efter).
-
Konstruktorn kommer att se ut så här:
+
Konstruktorn för vårt husdjursobjekt kommer att se ut så här:
<pre>
<pre>
Rad 105: Rad 103:
self.skick = 0
self.skick = 0
</pre>
</pre>
 +
 +
[[Bild:Tegel.jpg|frame|right]]
Den här konstruktorn har två parametrar, self (som ju alltid måste vara med)
Den här konstruktorn har två parametrar, self (som ju alltid måste vara med)
Rad 112: Rad 112:
det till noll. Varje gång man gör ett nytt objekt kommer konstruktorn att anropas.
det till noll. Varje gång man gör ett nytt objekt kommer konstruktorn att anropas.
-
'''Fråga: Vilket av följande måste en konstruktor ha?'''
+
Den andra specialmetoden vi ska ta upp här heter <code>__str__</code>, och det
-
# parametern self
+
speciella med den är att den anropas varje gång man försöker skriva ut ett
-
# en parameter för varje attribut
+
objekt med <code>print</code>. Här kan man alltså tala om hur man vill
-
# ett returvärde
+
att objektets data ska skrivas ut. Exempel:
-
'''Svar:'''<span style="color:white">Parametern self är det enda som måste vara med. Attributen kan få värden via parametrar (som namn ovan), men det är inte nödvändigt. Konstruktorn ska inte ha något returvärde.</span>
+
 
 +
<pre>
 +
def __str__(self):
 +
return self.namn + "*" + str(self.skick)
 +
</pre>
 +
Metoden <code>__str__</code> är särskilt användbar under tiden man arbetar
 +
med programmet, för att det blir enklare att göra kontrollutskrifter.
-
==Klassen==
+
===Klassen===
För att kunna skapa ett objekt måste man först definiera en klass.
För att kunna skapa ett objekt måste man först definiera en klass.
Rad 127: Rad 133:
<pre>
<pre>
-
class Husdjur(object):
+
# En klass som beskriver ett virtuellt husdjur.
-
# Ett virtuellt husdjur
+
# Attribut:
 +
# namn - djurets nanm
 +
# skick - ett heltal som beskriver djurets skick
 +
class Husdjur:
# Konstruktorn
# Konstruktorn
Rad 134: Rad 143:
self.namn = djurnamn
self.namn = djurnamn
self.skick = 0
self.skick = 0
 +
 +
# För utskrift med print
 +
def __str__(self):
 +
return self.namn + "*" + str(self.skick)
# Ger husdjuret bannor. Skick minskas.
# Ger husdjuret bannor. Skick minskas.
def banna(self):
def banna(self):
-
print
+
print()
-
print "- Fy på dig", self.namn, "!"
+
print("- Fy på dig", self.namn, "!")
self.skick -= 3
self.skick -= 3
Rad 167: Rad 180:
metod från ett objekt.
metod från ett objekt.
-
'''Fråga: Kan man skriva Husdjur.banna()?'''
+
===Exempel: Husdjursprogrammet===
-
 
+
-
'''Svar:'''<span style="color:white">Nej, man kan bara banna ett husdjursobjekt, inte hela klassen. </span>
+
-
 
+
-
 
+
-
 
+
-
==Exempel: Husdjursprogrammet==
+
Här följer hela programmet, först Husdjurs-klassen, och sedan huvudprogrammet.
Här följer hela programmet, först Husdjurs-klassen, och sedan huvudprogrammet.
Lägg märke till att alla metoderna i klassen är indenterade.
Lägg märke till att alla metoderna i klassen är indenterade.
<pre>
<pre>
-
class Husdjur(object):
+
# En klass som beskriver ett virtuellt husdjur.
-
# Ett virtuellt husdjur
+
# Attribut:
 +
# namn - djurets nanm
 +
# skick - ett heltal som beskriver djurets skick
 +
class Husdjur:
# Konstruktorn, initierar attributen namn och skick.
# Konstruktorn, initierar attributen namn och skick.
Rad 188: Rad 198:
# Visar husdjurets namn och skick
# Visar husdjurets namn och skick
def visaSkick(self):
def visaSkick(self):
-
print self.namn, "är ",
+
print(self.namn, "är ", end=" ")
if self.skick > 5:
if self.skick > 5:
-
print "glad: (*_*)"
+
print("glad: (^_^)")
elif self.skick > 0:
elif self.skick > 0:
-
print "trött: (-z-)"
+
print("trött: (T_T)")
else:
else:
-
print "hungrig: (*o*)"
+
print("hungrig: ('o')")
print
print
# Ger husdjuret bannor. Skick minskas.
# Ger husdjuret bannor. Skick minskas.
def banna(self):
def banna(self):
-
print
+
print()
-
print "- Fy på dig", self.namn, "!"
+
print("- Fy på dig", self.namn, "!")
self.skick -= 3
self.skick -= 3
# Ger husdjuret mat. Skick ökar.
# Ger husdjuret mat. Skick ökar.
def mata(self, mat):
def mata(self, mat):
-
print
+
print()
for i in range(mat):
for i in range(mat):
-
print "GLUFS",
+
print("GLUFS", end=" ")
self.skick += mat
self.skick += mat
# Leker med husdjuret. Skick kan öka eller minska.
# Leker med husdjuret. Skick kan öka eller minska.
def leka(self):
def leka(self):
-
print
+
print()
if self.skick < 0:
if self.skick < 0:
self.skick -= 1
self.skick -= 1
-
print self.namn, " vill inte leka."
+
print(self.namn, " vill inte leka.")
else:
else:
self.skick += 1
self.skick += 1
-
print "~~~~~~~~~~~ WHEEEEEEE! ~~~~~~~~~~~"
+
print("~~~~~~~~~~~ WHEEEEEEE! ~~~~~~~~~~~")
# Skriver ut avskedet.
# Skriver ut avskedet.
def avsked(self):
def avsked(self):
-
print
+
print()
-
print "Hejdå,", self.namn, "kommer att sakna dig!"
+
print("Hejdå,", self.namn, "kommer att sakna dig!")
# Här slutar Husdjursklassen
# Här slutar Husdjursklassen
Rad 229: Rad 239:
# -------- Här börjar huvudprogrammet -----------
# -------- Här börjar huvudprogrammet -----------
-
djurnamn = raw_input("Vad vill du döpa ditt husdjur till? ")
+
def main():
-
djur = Husdjur(djurnamn)
+
djurnamn = input("Vad vill du döpa ditt husdjur till? ")
-
djur.visaSkick()
+
djur = Husdjur(djurnamn)
-
svar = raw_input(" Vill du \n banna \n mata \n leka med \n ditt husdjur? " )
+
-
while svar:
+
-
if svar[0]=="m":
+
-
bullar = input("Hur många bullar? ")
+
-
djur.mata(bullar)
+
-
elif svar[0]=="b":
+
-
djur.banna()
+
-
elif svar[0]=="l":
+
-
djur.leka()
+
-
else:
+
-
print "Hursa? "
+
djur.visaSkick()
djur.visaSkick()
-
svar = raw_input(" Vill du \n banna \n mata \n leka med \n ditt husdjur? " )
+
svar = input(" Vill du \n banna \n mata \n leka med \n ditt husdjur? " )
-
djur.avsked()
+
while svar:
 +
if svar[0]=="m":
 +
bullar = int(input("Hur många bullar? "))
 +
djur.mata(bullar)
 +
elif svar[0]=="b":
 +
djur.banna()
 +
elif svar[0]=="l":
 +
djur.leka()
 +
else:
 +
print("Hursa? ")
 +
djur.visaSkick()
 +
svar = input(" Vill du \n banna \n mata \n leka med \n ditt husdjur? " )
 +
djur.avsked()
 +
 
 +
# Vi lägger in huvudprogrammet i en funktion för att undvika globala variabler.
 +
main()
</pre>
</pre>
-
Provkör programmet och svara på följande frågor.
+
Provkör programmet och svara på [[6. Övningar|följande frågor]].
-
* '''Fråga: Hur många objekt skapas i programmet?'''
+
==Sortering av en lista med objekt==
-
'''Svar:'''<span style="color:white">Bara ett - variabeln djur. </span>
+
Oftast skapar man fler än ett objekt i sitt program. Då är det praktiskt
 +
att spara objekten i en lista. En lista med objekt kan enkelt sorteras efter
 +
sina attribut. Men på något sätt måste man ange vilket attribut man vill
 +
sortera på. Är det namn eller skick?
-
* '''Fråga: När metoden visaSkick skriver ut att husdjuret är trött - vilka värden har attributet skick då?'''
+
Så här kan sortering av en lista skrivas:
-
'''Svar:'''<span style="color:white">Attributet skick har något av värdena 1,2,3,4 eller 5</span>
+
<pre>
 +
lista.sort(key = lambda x:x.attr)
 +
</pre>
-
* '''Fråga: Hur avslutar man programmet?'''
+
Parametern <code>key</code> i sort visar att man vill ange vilket attribut
 +
man vill sortera på. Uttrycket <code>lambda x:x.attribut</code> är som en
 +
liten funktion i miniatyr där parametern står före kolonet och returvärdet efter.
 +
Om vi tänker oss att x är objektet så är attr det av objektets attribut som vi
 +
vill sortera på.
 +
 +
Om det attribut man sorterar på är en sträng görs sorteringen
 +
efter bokstavsordning. Är attributet ett tal så blir objekten sorterade i
 +
stigande ordning. Vi förenklar Husdjursklassen en aning och visar
 +
med exemplet nedan hur sorteringen kan göras i praktiken:
-
'''Svar:'''<span style="color:white">När man trycker på Retur avslutas programmet. Lägg gärna till en print-sats som upplyser användaren om det! </span>
+
<pre>
 +
import random
-
* '''Fråga: Hur många metoder finns det i klassen Husdjur?'''
+
# En klass som beskriver ett virtuellt husdjur.
 +
# Attribut:
 +
# namn - djurets nanm
 +
# skick - ett heltal som beskriver djurets skick
 +
class Husdjur:
-
'''Svar:'''<span style="color:white">Det finns sex metoder, inklusive konstruktorn.</span>
+
# Konstruktorn, initierar attributen namn och skick.
 +
def __init__(self, djurnamn):
 +
self.namn = djurnamn
 +
self.skick = random.randrange(-5,6)
 +
 +
# För utskrift av ett objekt med print
 +
def __str__(self):
 +
return self.namn + "*" + str(self.skick)
 +
 +
# ------- Här slutar Husdjursklassen ---------
-
* '''Fråga: Kan man få programmet att krascha?'''
+
# En funktion för utskrift av listan
 +
def skrivListan(listan):
 +
for o in listan:
 +
print(o, end=" ")
 +
print("\n")
-
'''Svar:'''<span style="color:white">Javisst, prova att skriva tre (istället för 3) när du matar husdjuret med bullar. Här skulle det behövas lite felhantering!</span>
+
# -------- Här börjar huvudprogrammet ---------
 +
def main():
 +
djurlista = [Husdjur("Missan"), Husdjur("Blixten"), Husdjur("Fido"), Husdjur("Miso")]
 +
print("Så här ser listan ut från början:")
 +
skrivListan(djurlista)
-
==Test==
+
djurlista.sort(key = lambda husdjur:husdjur.namn)
 +
print("Nu är listan sorterad efter namn, i bokstavsordning:")
 +
skrivListan(djurlista)
 +
 +
djurlista.sort(key = lambda husdjur:husdjur.skick)
 +
print("Nu är listan sorterad efter skick, i stigande ordning:")
 +
skrivListan(djurlista)
-
TODO
 
 +
# Vi lägger in huvudprogrammet i en funktion för att undvika globala variabler.
 +
main()
 +
</pre>
-
==Inlämningsuppgift 3==
 
-
Du ska skriva ett program som simulerar ett nöjesfält.
+
==Kort sammanfattning==
-
Använd objekt för att representera attraktionerna.
+
-
En attraktion kan till exempel ha namn, minimilängd (för att få åka),
+
-
antal passagerare och magpirrfaktor. Den ska kunna göra reklam för sig,
+
-
startas, stoppas och haverera.
+
-
Skriv också ett huvudprogram där användaren får välja mellan tre olika
+
* Ett objekt är en datatyp som kan innehålla både data (attribut) och funktioner (metoder).
-
attraktioner. Vald attraktion ska startas, kanske haverera
+
* Den del av programmet där man definierar attribut och metoder kallas en klass.
-
(slumpa fram haverier) och stannas. När attraktionen är igång
+
* En klass är en mall för ett objekt. Ett objekt är en instans av en klass.
-
ska det synas på skärmen, man skulle kunna tänka sig ett Iiiih
+
* <code>self</code> är en referensvariabel som refererar inifrån objektet till objektet självt.
-
från berg-och-dalbanan, skratt från lustiga huset och så vidare.
+
-
Programmet ska finnas i en fil med namnet <code>Uppgift3.py</code>. Följ den här mallen:
+
* Följande skapar ett objekt:
 +
<pre>katten = Husdjur("Missan")</pre>
 +
Konstruktorn __init__ anropas automatiskt och attributen ges värden. En referens till objektet returneras (till katten).
 +
* Metoder anropas sedan via objektet:
 +
<pre>katten.banna()
 +
katten.mata(bullar)
 +
katten.leka()</pre>
 +
I övrigt så fungerar metoder som vilken funktion som helst, i det att de kan ha parametrar och returvärden.
-
<pre># Programmeringsteknik webbkurs KTH inlämningsuppgift 3.
 
-
# <Ditt namn>
 
-
# <Datum>
 
-
# <Kort beskrivning av vad programmet gör>
 
-
<Programkod></pre>
+
==Test 6==
-
Innan du skickar in programmet så ska du testa att det fungerar. Se till att du har provat alla klassens
+
Dags för test nummer 6. Testet hittar du som vanligt under rubriken Examination
-
metoder, och fått se alla utskrifter som ditt program gör.
+
på kursens förstasida. Även detta test rättas automatiskt och du har möjlighet
 +
att göra om testet flera gånger om du inte lyckas på första försöket.
 +
 
 +
 
 +
==Inlämningsuppgift 3==
-
När du har testat ditt program grundligt så går du till studentportalen och klickar dig fram till Inlämningsuppgift&nbsp;3 och där lämnar du in filen Uppgift3.py. Observera att filen Uppgift3.py måste vara i textformat - vilket den automatiskt blir om du skapar den med hjälp av IDLE. Detta för att vi ska kunna prova och testköra ditt program.
+
[[6. Inlämningsuppgift 3|Inlämningsuppgift 3: Nöjesfält]]

Nuvarande version

       Teori          Övningar          Exempel1          Exempel2          Inlämningsuppgift 3: Nöjesfält      


Innehåll

Objektorientering

Objektorienterad programmering är ett sätt att kombinera data och funktioner för att bilda objekt. Objekten är ofta modeller av verkliga ting. Om vi vill skriva ett program för att simulera ett rymdskepp kan vi till exempel ha hastighet och lägeskoordinater som data. Rymdskeppets funktioner kan vara att accelerera i en viss riktning och att rotera.

Två rymdskepp

För att kunna använda objekt i sitt program måste man först definiera en klass. Klassen beskriver vilka data ett objekt ska kunna innehålla och vilka funktioner det ska ha. Om vi definierat en klass för rymdskepp kan vi sedan skapa hur många rymdskepps-objekt vi vill!

Det stora exemplet i det här avsnittet kommer att handla om ett virtuellt husdjur. Ett husdjur kan ju ha många egenskaper, men vi väljer ut två att ta med i vår klass: namn och skick (ett heltal som talar om hur den känner sig just nu). Användaren får själv välja namn på sitt husdjur, och husdjurets skick ska påverkas av hur den behandlas.

Attribut

De variabler som används för att lagra data som hör till objektet kallas attribut. Våra husdjursobjekt ska alltså ha attributen namn och skick. Om man har flera objekt av samma typ är attributens värde helt oberoende av varandra. Två olika husdjur får ha olika namn och olika skick.

Det finns en synlig skillnad mellan attribut och vanliga variabler. Inuti klassen använder man alltid ordet self när man vill komma åt ett attribut. Man kan till exempel skriva så här:

self.namn = "Fido"

Med self menar man objektet självt.

Metoder

Funktionerna som hör till ett objekt kallas metoder. För att en funktion ska bli en metod måste den definieras inuti klassen. Den första parametern i en metod måste alltid vara self. Via self kan metoden använda objektets attribut.

Säg att vi vill ha en metod som ger vårt husdjur bannor (i uppfostrande syfte). Metoden ska visa bannorna, och även minska värdet på skick eftersom husdjuret blir på sämre humör.

    def banna(self):
        print()
        print("- Fy på dig", self.namn, "!")
        self.skick -= 3

Som synes skriver man en metod precis som en funktion, sånär som på ordet self. Samma regler för parametrar och returvärden gäller.

Husdjursklassen ska så småningom få metoder som gör följande:

  • skapar ett husdjursobjekt och ger attributen värden
  • visar i vilket skick husdjuret är
  • bannar husdjuret
  • matar husdjuret
  • leker med husdjuret
  • tar avsked av husdjuret


Speciella metoder: konstruktorn och str

Metoder får man döpa precis som man vill. Men det finns ett par metodnamn som har speciell betydelse för Python. Här tar vi upp två av dessa. Metodnamnen börjar och slutar med två understrykningstecken, så det finns ingen risk att man råkar välja namnen av misstag.

Konstruktorn är en speciell metod som man skriver för att initiera objekt, dvs ge objektets attribut de värden de ska ha från början. Konstruktorn anropas automatiskt varje gång ett objekt skapas. I Python måste man döpa sin konstruktor till __init__ (alltså init med två understrykningstecken både före och efter).

Konstruktorn för vårt husdjursobjekt kommer att se ut så här:

    def __init__(self, djurnamn):
        self.namn = djurnamn
        self.skick = 0

Den här konstruktorn har två parametrar, self (som ju alltid måste vara med) och djurnamn. Raden self.namn = djurnamn skapar attributet namn och initierar det till värdet av parametern djurnamn. På samma sätt skapar raden self.skick = 0 attributet skick och initierar det till noll. Varje gång man gör ett nytt objekt kommer konstruktorn att anropas.

Den andra specialmetoden vi ska ta upp här heter __str__, och det speciella med den är att den anropas varje gång man försöker skriva ut ett objekt med print. Här kan man alltså tala om hur man vill att objektets data ska skrivas ut. Exempel:

    def __str__(self):
        return self.namn + "*" + str(self.skick)

Metoden __str__ är särskilt användbar under tiden man arbetar med programmet, för att det blir enklare att göra kontrollutskrifter.

Klassen

För att kunna skapa ett objekt måste man först definiera en klass. Det är i klassen man skriver de metoder som objektet ska ha. Klasser brukar ha namn som börjar med versal, så att man lätt ska kunna se att det är en klass. Så här långt har vi hunnit i vår husdjursklass hittills:

# En klass som beskriver ett virtuellt husdjur.
# Attribut:
#    namn - djurets nanm
#    skick - ett heltal som beskriver djurets skick
class Husdjur:

    # Konstruktorn
    def __init__(self, djurnamn):
        self.namn = djurnamn
        self.skick = 0

    # För utskrift med print
    def __str__(self):
        return self.namn + "*" + str(self.skick)

    # Ger husdjuret bannor. Skick minskas.
    def banna(self):
        print()
        print("- Fy på dig", self.namn, "!")
        self.skick -= 3

Med en klass är det likadant som med en funktion - det händer inget förrän man använder den i huvudprogrammet. För att skapa ett Husdjurs-objekt kan vi skriva:

djur = Husdjur("Muffin")

Det som händer här är att konstruktorn __init__ anropas, så att attributen skapas och initieras. Sen returneras ett Husdjurs-objekt, som lagras i variabeln djur

Nu har vi ett husdjursobjekt i variabeln djur. Hur anropar vi en av djurets metoder? Just nu finns bara metoden banna att välja på:

djur.banna()

När vi vill komma åt ett attribut inuti klassen använder vi ju en punkt, och ett liknande skrivsätt använder man alltså när man vill anropa en metod från ett objekt.

Exempel: Husdjursprogrammet

Här följer hela programmet, först Husdjurs-klassen, och sedan huvudprogrammet. Lägg märke till att alla metoderna i klassen är indenterade.

# En klass som beskriver ett virtuellt husdjur.
# Attribut:
#    namn - djurets nanm
#    skick - ett heltal som beskriver djurets skick
class Husdjur:

    # Konstruktorn, initierar attributen namn och skick.
    def __init__(self, djurnamn):
        self.namn = djurnamn
        self.skick = 0

    # Visar husdjurets namn och skick
    def visaSkick(self):       
        print(self.namn, "är ", end=" ")
        if self.skick > 5:
            print("glad: (^_^)")
        elif self.skick > 0:
            print("trött: (T_T)")
        else:
            print("hungrig: ('o')")
        print

    # Ger husdjuret bannor. Skick minskas.
    def banna(self):
        print()
        print("- Fy på dig", self.namn, "!")
        self.skick -= 3

    # Ger husdjuret mat. Skick ökar.
    def mata(self, mat):
        print()
        for i in range(mat):
            print("GLUFS", end=" ")
        self.skick += mat

    # Leker med husdjuret. Skick kan öka eller minska.
    def leka(self):
        print()
        if self.skick < 0:
            self.skick -= 1
            print(self.namn, " vill inte leka.")
        else:
            self.skick += 1
            print("~~~~~~~~~~~ WHEEEEEEE! ~~~~~~~~~~~")

    # Skriver ut avskedet.
    def avsked(self):
        print()
        print("Hejdå,", self.namn, "kommer att sakna dig!")

# Här slutar Husdjursklassen


#  --------  Här börjar huvudprogrammet -----------
def main():
    djurnamn = input("Vad vill du döpa ditt husdjur till? ")
    djur = Husdjur(djurnamn)
    djur.visaSkick()
    svar = input(" Vill du \n  banna \n  mata \n  leka med \n ditt husdjur? " )
    while svar:
        if svar[0]=="m":
            bullar = int(input("Hur många bullar? "))
            djur.mata(bullar)    
        elif svar[0]=="b":
            djur.banna()
        elif svar[0]=="l":
            djur.leka()
        else:
            print("Hursa? ")
        djur.visaSkick()
        svar = input(" Vill du \n  banna \n  mata \n  leka med \n ditt husdjur? " )
    djur.avsked()

# Vi lägger in huvudprogrammet i en funktion för att undvika globala variabler.
main()

Provkör programmet och svara på följande frågor.

Sortering av en lista med objekt

Oftast skapar man fler än ett objekt i sitt program. Då är det praktiskt att spara objekten i en lista. En lista med objekt kan enkelt sorteras efter sina attribut. Men på något sätt måste man ange vilket attribut man vill sortera på. Är det namn eller skick?

Så här kan sortering av en lista skrivas:

   lista.sort(key = lambda x:x.attr)

Parametern key i sort visar att man vill ange vilket attribut man vill sortera på. Uttrycket lambda x:x.attribut är som en liten funktion i miniatyr där parametern står före kolonet och returvärdet efter. Om vi tänker oss att x är objektet så är attr det av objektets attribut som vi vill sortera på.

Om det attribut man sorterar på är en sträng görs sorteringen efter bokstavsordning. Är attributet ett tal så blir objekten sorterade i stigande ordning. Vi förenklar Husdjursklassen en aning och visar med exemplet nedan hur sorteringen kan göras i praktiken:

import random

# En klass som beskriver ett virtuellt husdjur.
# Attribut:
#    namn - djurets nanm
#    skick - ett heltal som beskriver djurets skick
class Husdjur:

    # Konstruktorn, initierar attributen namn och skick.
    def __init__(self, djurnamn):
        self.namn = djurnamn
        self.skick = random.randrange(-5,6)
        
    # För utskrift av ett objekt med print
    def __str__(self):
        return self.namn + "*" + str(self.skick)
    
#  -------  Här slutar Husdjursklassen ---------

# En funktion för utskrift av listan
def skrivListan(listan):
    for o in listan:
        print(o, end=" ")
    print("\n")

#  --------  Här börjar huvudprogrammet ---------
def main():
    djurlista = [Husdjur("Missan"), Husdjur("Blixten"), Husdjur("Fido"), Husdjur("Miso")]

    print("Så här ser listan ut från början:")
    skrivListan(djurlista)

    djurlista.sort(key = lambda husdjur:husdjur.namn)
    print("Nu är listan sorterad efter namn, i bokstavsordning:")
    skrivListan(djurlista)
        
    djurlista.sort(key = lambda husdjur:husdjur.skick)
    print("Nu är listan sorterad efter skick, i stigande ordning:")
    skrivListan(djurlista)


# Vi lägger in huvudprogrammet i en funktion för att undvika globala variabler.
main()


Kort sammanfattning

  • Ett objekt är en datatyp som kan innehålla både data (attribut) och funktioner (metoder).
  • Den del av programmet där man definierar attribut och metoder kallas en klass.
  • En klass är en mall för ett objekt. Ett objekt är en instans av en klass.
  • self är en referensvariabel som refererar inifrån objektet till objektet självt.
  • Följande skapar ett objekt:
katten = Husdjur("Missan")

Konstruktorn __init__ anropas automatiskt och attributen ges värden. En referens till objektet returneras (till katten).

  • Metoder anropas sedan via objektet:
katten.banna()
katten.mata(bullar)
katten.leka()

I övrigt så fungerar metoder som vilken funktion som helst, i det att de kan ha parametrar och returvärden.


Test 6

Dags för test nummer 6. Testet hittar du som vanligt under rubriken Examination på kursens förstasida. Även detta test rättas automatiskt och du har möjlighet att göra om testet flera gånger om du inte lyckas på första försöket.


Inlämningsuppgift 3

Inlämningsuppgift 3: Nöjesfält