Osa 8

Klasser och objekt

I föregående avsnitt arbetade vi med listor, tuplar, ordlistor och strängar. Dessa är alla ganska speciella fall i Python-programmering. Pythons syntax har en unik, fördefinierad metod för att deklarera ett objekt som tillhör var och en av dessa typer:

# Listor deklareras med hakparenteser
lista = [1,2,3]

# Strängar deklareras med citationstecken
strang = "Hej alla!"

# Ordlistor deklareras med klammerparenteser
ordlista = {"ett": 1, "två:": 2}

# tuplar deklareras med parenteser
tupel = (1,2,3)

När någon annan typ av objekt deklareras måste vi anropa en speciell initialiseringsfunktion som kallas konstruktor. Låt oss ta en titt på hur man arbetar med bråk genom Fraction-klassen.

# vi använder klassen Fraction från modulen fractions
from fractions import Fraction

# vi skapar några nya bråktal
halv = Fraction(1,2)

tredjedel = Fraction(1,3)

tredje = Fraction(3,11)

# Tulostetaan
print(halv)
print(tredjedel)
print(tredje)

# Murtoluvuilla voi myös laskea
print(halv + tredjedel)
Exempelutskrift

1/2 1/3 3/11 5/6

Som du kan se ovan, ser metodkallningar för konstruktorer lite annorlunda ut än de normala metodkallningar som vi har stött på tidigare. För det första är de inte kopplade till något objekt med punktnotationen (eftersom konstruktoranropet behövs för att skapa ett objekt i första hand). Konstruktorsmetoden skrivs också med stor bokstav: [half = Fraction(1,2)]. Låt oss titta närmare på hur objekt konstrueras genom att bekanta oss med begreppet klass.

En klass är ritningen till ett objekt

Vi har redan använt termen klass i materialet många gånger. I exemplet ovan importerade vi t.ex. klassen Fraction från modulen fractions. Nya bråktalsobjekt skapades genom att kalla på konstruktorsmetoden för klassen Fraction.

En klassdefinition innehåller strukturen och funktionaliteterna för alla objekt som representerar den. Därför kallas klasser ibland till objektens ritningar. En klassdefinition berättar alltså till oss vilken typ av data ett objekt innehåller och definierar de metoder som kan användas på objektet. Objektorienterad programmering är ett programmeringsparadigm där programmets funktionalitet är knuten till användningen av klasser och objekt som skapas baserat på dessa.

En klassdefinition kan användas för att skapa flera objekt. Som tidigare nämnts är objekt oberoende av varandra. Ändringar som görs till ett objekt påverkar i allmänhet inte de andra objekten som är samma klass. Varje objekt har sin egen unika uppsättning dataattribut. Det kan vara bra att tänka på denna förenkling av förhållandet mellan klass och objekt:

  • En klass definierar variablerna
  • när ett objekt skapas tilldelas dessa variabler värden

Vi kan alltså använda ett objekt av typen Fraction för att komma åt täljaren och nämnaren i ett bråktal:

from fractions import Fraction

tal = Fraction(2,5)

# Skriv ut täljaren
print(tal.numerator)

# ... och sedan nämnaren
print(tal.denominator)
Exempelutskrift

2 5

Klassdefinitionen för Fraction innehåller deklarationer för variablerna numerator och denominator. Varje objekt som skapas baserat på klassen har sina egna specifika värden som tilldelas dessa variabler.

På samma sätt innehåller objekt som skapats baserat på klassen date sina egna unika värden för datumets år, månad och dag:

from datetime import date

jul = date(2020, 12, 24)
midsommar = date(2020, 6, 20)

# Vi skriver ut bägges månad
print(jul.month)
print(midsommar.month)
Exempelutskrift

12 6

Definitionen av klassen date innehåller deklarationer av variablerna year, month och day. När ett nytt datumobjekt skapas baserat på klassen tilldelas dessa variabler värden. Varje objekt har sina egna unika värden som tilldelas dessa variabler.

Funktioner som arbetar med objekt

Att passera ett objekt som ett argument till en funktion borde vara bekant för dig vid det här laget eftersom vi har gjort det redan många gånger i den här kursen. Låt oss ta en titt på följande exempel. Här har vi en funktion som kontrollerar om date-objektet som passeras som argument infaller på en helg:

def redan_veckoslut(dag: date):
    veckodag = dag.isoweekday()
    return veckodag == 6 or veckodag == 7

Denna funktion använder metoden isoweekday, som definieras i klassdefinitionen för klassen date, och returnerar ett heltalsvärde på det sättet att om det angivna datumet är en måndag returnerar den 1, och om det är en tisdag returnerar den 2, och så vidare.

jul = date(2020, 12, 24)
midsommar = date(2020, 6, 20)

print(redan_veckoslut(jul))
print(redan_veckoslut(midsommar))
Exempelutskrift

False True

Metoder vs variabler

När du arbetar med ett objekt av typen date kanske du märker att det finns en liten skillnad mellan hur variablerna i objektet åtkoms jämfört med hur metoderna som är kopplade till objekten åtkoms:

dag = date(2020, 12, 24)

# vi kallar metoden
veckodag = dag.isoweekday()

# vi använder en variabel
manad = dag.month

print("Veckodag:", veckodag)
print("Månad:", kuukausi)
Exempelutskrift

Veckodag: 4 Månad: 12

Veckodagen som datumet infaller på är tillgänglig via metoden isoweekday:

veckodag = dag.isoweekday()

Detta är en metodkallelse, alltså finns det parenteser efter namnet på metoden. Om du lämnar bort parenteserna uppstår det inte något fel, men resultatet blir konstigt:

veckodag =  dag.isoweekday
print("Veckodag:", veckodag)
Exempelutskrift

Veckodag: <built-in method isoweekday of datetime.date object at 0x10ed66450>

Månaden av ett date-objekt är en variabel, alltså kan det tillgivna värdet kommas åt med en referens.

manad = dag.month

Lägg märke till att det inte finns parenteser här. Att sätta in parenteser skulle orsaka ett fel:

manad = dag.month()
Exempelutskrift
Traceback (most recent call last): File "", line 1, in TypeError: 'int' object is not callable
Loading
Loading
Du har nått slutet av den här delen! Fortsätt till nästa del:

Se dina poäng genom att klicka på cirkeln nere till höger av sidan.