Egna klasser
En klass definieras med nyckelordet class
. Syntaxen ser ut enligt följande:
class KlassNamn:
# Klassdefinitionen
Klasser namnges vanligtvis med kamelnotation. Detta innebär att alla ord i klassnamnet skrivs tillsammans, utan mellanslag, och att varje ord börjar med stor bokstav. Följande exempel på klassnamn följer denna konvention:
Veckodag
Bankkonto
BiblioteksDatabas
PythonKursBetyg
En enskild klassdefinition bör representera en enskild helhet, vars innehåll bör vara sammanlänkat på något sätt. I mer komplicerade program kan klasser innehålla medlemmar av andra klasser. Till exempel kan klassen Kurs
innehålla objekt av klasserna Lektion
, ÖvningsTillfälle
osv.
Låt oss ta en titt på strukturen för en klassdefinition.
class Bankkonto:
pass
Koden ovan talar om för Python att vi här definierar en klass med namnet Bankkonto
. Klassen innehåller ingen funktionalitet ännu, men vi kan redan skapa ett objekt baserat på klassen.
Låt oss titta på ett program där två variabler läggs till ett Bankkonto
-objekt: saldo
och ägare
. Alla variabler som är kopplade till ett objekt kallas dess attribut, eller mer specifikt, dataattribut, eller ibland instansvariabler.
De attribut som är kopplade till ett objekt kan nås via objektet:
class Bankkonto:
pass
peters_konto = Bankkonto()
peters_konto.agare = "Peter Python"
peters_konto.saldo = 5.0
print(peters_konto.agare)
print(peters_konto.saldo)
Peter Python 5.0
Dataattributen är endast tillgängliga via det objekt som de är kopplade till. Varje Bankkonto-objekt som skapas baserat på Bankkonto-klassen har sina egna värden kopplade till dataattributen. Dessa värden kan nås genom att hänvisa till objektet i fråga:
konto = Bankkonto()
konto.saldo = 155.50
print(konto.saldo) # Detta refererar till dataattributen saldo, som är kopplad till kontot
print(saldo) # DETTA ORSAKAR ETT FEL, eftersom det inte finns någon sådan oberoende variabel, och objektreferensen saknas
Att lägga till en konstruktor
I exemplet ovan såg vi att en ny instans av en klass kan skapas genom att anropa klassens konstruktormetod på följande sätt: KlassensNamn()
. Ovan kopplade vi sedan dataattribut till objektet separat, men det är ofta bekvämare att skicka dessa initiala värden för attribut direkt när objektet skapas. I exemplet ovan hade vi först ett Bankkonto-objekt utan dessa attribut, och attributen existerade först efter att de uttryckligen hade deklarerats.
Att deklarera attribut utanför konstruktorn leder till en situation där olika instanser av samma klass kan ha olika attribut. Följande kod ger ett fel eftersom vi nu har ett annat Bankkonto-objekt
, pernillas_konto
, som inte innehåller samma attribut:
class Bankkonto:
pass
peters_konto = Bankkonto()
peters_konto.agare = "Peter"
peters_konto.saldo = 1400
pernillas_konto = Bankkonto()
pernillas_konto.agare = "Pernilla"
print(peters_konto.saldo)
print(pernillas_konto.saldo) # DETTA ORSAKAR ETT FEL
Istället för att deklarera attribut efter att varje instans av klassen har skapats, är det därför oftast en bättre idé att initialisera attributens värden när konstruktorn anropas. Eftersom klassdefinitionen Bankkonto för närvarande bara är en ram, antas konstruktormetoden implicit av Python-tolkaren, men det är möjligt att definiera egna konstruktormetoder, och det är precis vad vi kommer att göra nu.
En konstruktormetod är en metoddeklaration med det speciella namnet __init__
, som vanligtvis inkluderas i början av en klassdefinition.
Låt oss ta en titt på en Bankkonto
-klass där vi nu även definierat en konstruktor:
class Bankkonto:
# Konstruktorn
def __init__(self, saldo: float, agare: str):
self.saldo = saldo
self.agare = agare
Namnet på konstruktorn är alltid __init__
. Lägg märke till de två understrecken på båda sidorna av ordet init
.
Den första parametern i en konstruktorsdefinition heter alltid self
. Detta refererar till själva objektet och är nödvändigt för att deklarera alla attribut som är knutna till objektet. Tilldelningen
self.saldo = saldo
tilldelar objektets saldoattribut det sald som tagits emot som argument. Det är vanligt att använda samma variabelnamn för parametrarna och dataattributen som definieras i en konstruktor, men variabelnamnen self.saldo
och saldo
ovan hänvisar till två olika variabler:
-
Variabeln
self.saldo
är ett attribut för objektet. Varje Bankkonto-objekt har sitt eget saldo. -
Variabeln
saldo
är en parameter i konstruktorsmetoden__init__
. Dess värde sätts till det värde som skickas som argument när konstruktorn anropas (dvs. när en ny instans av klassen skapas).
När vi har definierat parametrarna för konstruktorsmetoden kan vi skicka de önskade initiala värdena för dataattributen som argument när ett nytt objekt skapas:
class Bankkonto:
# Konstruktorn
def __init__(self, saldo: float, agare: str):
self.saldo = saldo
self.agare = agare
# Parametern self ges inget värde, utan Python ger ett sådant automatiskt
peters_konto = Bankkonto(100, "Peter Python")
pernillas_konto = Bankkonto(20000, "Pernilla Pythonson")
print(peters_konto.saldo)
print(pernillas_konto.saldo)
100 20000
Det är nu mycket enklare att arbeta med Bankkonto-objekten, eftersom värdena kan skickas när objektet skapas, och de två separata instanserna kan hanteras på ett mer förutsägbart och enhetligt sätt. Att deklarera dataattribut i konstruktorn säkerställer också att attributen verkligen deklareras, och att de önskade initiala värdena alltid ges av programmeraren som använder klassen.
Det är fortfarande möjligt att ändra de initiala värdena för dataattributen senare i programmet:
class Bankkonto:
# Konstruktorn
def __init__(self, saldo: float, agare: str):
self.saldo = saldo
self.agare = agare
peters_konto = Bankkonto(100, "Peter Python")
print(peters_konto.saldo)
# Ändra saldot till 1500
peters_konto.saldo = 1500
print(peters_konto.saldo)
# Vi lägger till 2000 till saldot
peters_konto.saldo += 2000
print(peters_konto.saldo)
100 1500 3500
Låt oss titta på ett annat exempel på klasser och objekt. Vi ska skriva en klass som modellerar lotteridragning:
from datetime import date
class LotteriDragning:
def __init__(self, vecka: int, datum: date, nummer: list):
self.vecka = vecka
self.datum = datum
self.nummer = nummer
# Vi skapar ett nytt LotteriDragning-objekt
runda1 = LotteriDragning(1, date(2021, 1, 2), [1,4,8,12,13,14,33])
# Vi skriver ut resultatet
print(runda1.vecka)
print(runda1.datum)
for nummer in runda1.nummer:
print(nummer)
1 2021-01-02 1 4 8 12 13 14 33
Som du kan se ovan kan attributen vara av vilken typ som helst. Här har varje LotteriDragning-objekt attribut av typerna list
och date
.
Användning av objekt från egengjorda klasser
Objekt som bildas från dina egna klassdefinitioner skiljer sig inte från andra Python-objekt. De kan skickas som argument och returnera värden precis som alla andra objekt. Vi kan till exempel skriva hjälpfunktioner för att arbeta med bankkonton:
# funktionen skapar ett nytt bankkonto-objekt och returnerar det
def oppna_konto(namn: str):
nytt_konto = Bankkonto(0, namn)
return nytt_konto
# denna funktion lägger till det belopp som anges som argument till saldot som anges som argument
def lagg_in_pengar_pa_kontot(konto: Bankkonto, summa: int):
konto.saldo += summa
peters_konto = oppna_konto("Peter Python")
print(peters_konto.saldo)
lagg_in_pengar_pa_kontot(peters_konto, 500)
print(peters_konto.saldo)
0 500
Se dina poäng genom att klicka på cirkeln nere till höger av sidan.