Detta skapar en PDF som du sedan kan skriva ut. Du kan även spara ner PDFn och skriva ut senare.
Titel på utskriften?
Tack för ditt bidrag
Om vi kan använda det så lägger vi upp det på sidan. Nedan en länk till ditt bidrag om du vill spara det.
Spara som ...
Du sparar ditt skript under detta namn och kan sedan hämta tillbaka det med samma namn.
Läs in
Läs in ett tidigare sparat skript. Obs att du enbart kan läsa in skript i den webbläsare där du sparade skriptet. Vill du kunna läsa in och spara skript oberoende av webbläsare, så behöver du skaffa ett login (enkelt och gratis).
Skicka in bidrag
Föreslå rubrik
Beskriv vad din kod gör
Skapa kort länk
Använd en kort URL för att skicka länk till koden via SMS eller epost. När mottagaren klickar på länken, så öppnas denna webbsida, med din kod och din text. Länken rensas bort automatiskt om den inte används.
Rubrik (frivilligt)
Beskrivning (frivilligt)
Länk (kopiera hela)
Klasser
Tänka i objekt
Säg att du ska tillverka ett dator-program som håller koll på eleverna i en skola. Dvs, uppgifter om eleverna alltså.
En elev har bl.a. ett namn, både förnamn och efternamn (attribut). Vi måste veta ett telefonnummer också, så vi kan ringa eleven. Vi måste också veta vilken klass eleven går i. Vi måste veta mycket mer såklart, man vi begränsar oss lite i detta exempel. Vi vill kunna skriva ut elevens uppgifter (metod).
Skapa en klass
Vi tänker oss en mall (prototyp, skiss, ritning) med den data som vi vill lagra. Vi kallar denna mall för klass. I denna klass listar vi alla de attribut (variabler) vi behöver, eventuellt med standardvärden (default-värden).
Observera att denna klass bara är en mall. Vi kan inte lagra något där. För att kunna använda vår klass ("mall") så skapar vi ett eller flera eller tusentals instanser, alltså objekt med korrekt info/data, utifrån den.
Skapa ett objekt av vår klass gör vi med nyelev = Elev() här nedan.
class Elev:
fornamn = "Ej imtatat"
efternamn = "Ej imtatat"
tele = "okänt"
klass = "okänt"
nyelev = Elev()
print(nyelev.fornamn)
class Elev:
fornamn = "Ej imtatat"
efternamn = "Ej imtatat"
tele = "okänt"
klass = "okänt"
nyelev = Elev()
print(nyelev.fornamn)
Objektet nyelev kan vi nu använda. Objektet huserar nu alla de olika variabler vi angav i vår klass.
I ovan exempel får vi svaret "ej inmatat", när vi kör koden, vilket är rimligt, då vi skapade en elev men angav inget nytt namn på eleven, så det blev default -värdet som låg kvar. Vill vi ange namn får vi göra såhär.
Det finns ett proffsigare sätt att initiera våra skapade objekt, som också bjuder på en del extrafunktioner kommer det visa sig (längre fram).
__init__ -iera en klass
Konstruktionen är följande, vi lägger till en __init__ i klassen. Det brukar heta konstruktor (tänk konstruktör, skapare). Men det är ju redan tillräckligt tydligt, eller hur? Du ser ju själv att det står __init__. Det är precis vad vi gör!
Genom att lägga till en initiering i klassen, så kan vi parallellt med att vi skapar objektet också tilldela alla dess värden. Vi skapar en instans av klassen, i detta fall Anders Andersson. Han är en instans.
class Elev:
def __init__(self, f, e, t, k):
self.fornamn = f
self.efternamn = e
self.tele = t
self.klass = k
nyelev = Elev("Anders","Andersson","070707","TKINT")
print(nyelev.fornamn)
class Elev:
def __init__(self, f, e, t, k):
self.fornamn = f
self.efternamn = e
self.tele = t
self.klass = k
nyelev = Elev("Anders","Andersson","070707","TKINT")
print(nyelev.fornamn)
Samtidigt som vi skapar ett nytt Elev -objekt nyelev = Elev( ... ), så kommer alltså våra argument skickas över till __init__ som i sin tur skickar in dem i vår Elev -instans. Så när kodraden är utförd är instansen nyelev full med data.
Self är en referens som refererar till själva klassen. Tänk såhär: I alla funktioner så blir variablerna lokala. Så i vår initieringsfunktion, om vi inte refererade till omgivande klassen, så skulle alla data stanna i och försvinna med initieringsfunktionen.
På detta sätt överförs data till instansens variabler (instansvariabler) och blir kvar där.
Vi kan skapa många instanser av vår klass och då blir det också tydligare vad själv poängen med detta är.
class Elev:
def __init__(self, f, e, t, k):
self.fornamn = f
self.efternamn = e
self.tele = t
self.klass = k
elever = [
Elev("Anders","Andersson","070707","TKINT"),
Elev("Per","Persson","060708090","TKINT"),
Elev("Nils","Nilsson","706050403","TKINT"),
Elev("Ols","Olsson","09090909","TKINT")
]
print(elever[0].fornamn)
print(elever[1].fornamn)
print(elever[2].fornamn)
print(elever[3].fornamn)
class Elev:
def __init__(self, f, e, t, k):
self.fornamn = f
self.efternamn = e
self.tele = t
self.klass = k
elever = [
Elev("Anders","Andersson","070707","TKINT"),
Elev("Per","Persson","060708090","TKINT"),
Elev("Nils","Nilsson","706050403","TKINT"),
Elev("Ols","Olsson","09090909","TKINT")
]
print(elever[0].fornamn)
print(elever[1].fornamn)
print(elever[2].fornamn)
print(elever[3].fornamn)
En klass kan innehålla metoder. Så när en ny instans av klassen skapas, så hänger den här metoden med och kan användas. Vi kan tex skriva en metod skrivut() för att skriva ut all data. Vi lägger alltid till parametern self när vi skriver metoden, därför att den parametern läggs till automatiskt vid anropet. Self behövs så att vi kan referera instansens variabler, så att vi får tag i dem och kan skriva ut dem.
class Elev:
def __init__(self, f, e, t, k):
self.fornamn = f
self.efternamn = e
self.tele = t
self.klass = k
def skrivut(self):
print(f"{self.fornamn} {self.efternamn} {self.klass}")
elever = [
Elev("Anders","Andersson","070707","TKINT"),
Elev("Per","Persson","060708090","TKINT"),
Elev("Nils","Nilsson","706050403","TKINT"),
Elev("Ols","Olsson","09090909","TKINT")
]
for i in range(0,len(elever)):
elever[i].skrivut()
class Elev:
def __init__(self, f, e, t, k):
self.fornamn = f
self.efternamn = e
self.tele = t
self.klass = k
def skrivut(self):
print(f"{self.fornamn} {self.efternamn} {self.klass}")
elever = [
Elev("Anders","Andersson","070707","TKINT"),
Elev("Per","Persson","060708090","TKINT"),
Elev("Nils","Nilsson","706050403","TKINT"),
Elev("Ols","Olsson","09090909","TKINT")
]
for i in range(0,len(elever)):
elever[i].skrivut()
Vi kan nu loopa över alla våra instanser och printa ut dess data.
Printbar klass med __str__
Visst hade det varit coolt att kunna skriva ut vår egna klass med den vanliga print -funktionen? Print kan ju skriva allt annat här i världen, så varför inte vår egna klass? Det finns något i python som kallas dundermetoder. Om du bara ska lära dig en enda dundermetod, så är det __str__. Se nedan:
class Elev:
def __init__(self, f, e, t, k):
self.fornamn = f
self.efternamn = e
self.tele = t
self.klass = k
def __str__(self):
return(f"{self.fornamn} {self.efternamn}\n{self.klass}")
elever = [
Elev("Anders","Andersson","070707","TKINT"),
Elev("Per","Persson","060708090","TKINT"),
Elev("Nils","Nilsson","706050403","TKINT"),
Elev("Ols","Olsson","09090909","TKINT")
]
for elev in elever:
print(elev)
class Elev:
def __init__(self, f, e, t, k):
self.fornamn = f
self.efternamn = e
self.tele = t
self.klass = k
def __str__(self):
return(f"{self.fornamn} {self.efternamn}\n{self.klass}")
elever = [
Elev("Anders","Andersson","070707","TKINT"),
Elev("Per","Persson","060708090","TKINT"),
Elev("Nils","Nilsson","706050403","TKINT"),
Elev("Ols","Olsson","09090909","TKINT")
]
for elev in elever:
print(elev)
Om vi definierat en __str__ så kommer den anropas ifall vi använder print. Visst är det coolt!
instans & klassvariabler
Vi hade kunnat tänka oss nedanstående. Eftersom alla elever går på samma skola hade vi kunnat göra såhär. Alla instanser skulle då även ha en variabel som heter skola med värdet CTH. Vi kallar denna variabel för klassvariabel, eftersom den ligger på klass-nivå. Medans fornamn, efternamn, tele och klass ligger på instansnivå, dvs de initieras med egna värden varje gång en ny instans skapas.
class Elev:
skola = "CTH"
def __init__(self, f, e, t, k):
self.fornamn = f
self.efternamn = e
self.tele = t
self.klass = k
def __str__(self):
return(f"{self.fornamn} {self.klass} {self.skola}")
elever = [
Elev("Anders","Andersson","070707","TKINT"),
Elev("Per","Persson","060708090","TKINT"),
Elev("Nils","Nilsson","706050403","TKINT"),
Elev("Ols","Olsson","09090909","TKINT")
]
for elev in elever:
print(elev)
class Elev:
skola = "CTH"
def __init__(self, f, e, t, k):
self.fornamn = f
self.efternamn = e
self.tele = t
self.klass = k
def __str__(self):
return(f"{self.fornamn} {self.klass} {self.skola}")
elever = [
Elev("Anders","Andersson","070707","TKINT"),
Elev("Per","Persson","060708090","TKINT"),
Elev("Nils","Nilsson","706050403","TKINT"),
Elev("Ols","Olsson","09090909","TKINT")
]
for elev in elever:
print(elev)
Men vi kan fortfarande komma åt vår klassvariabel med self vilket du ser i utskriften ovan och vi hade omvänt kunna sätta ett värde på den via init.
Det är mest för att kunna prata om det som man kallar variabler på klass-nivå för klassvariabler (nära ordet class i classen) och variabler på instans-nivå för instansvariabler (ligger i __init__).
Tanken är att klassvariabler används för sådant med mycket default -värden och instansvariabler för det som är unika för varje instans.
Om du kommer från något annat programspråk, t.ex. C++ eller C#, Java eller vad som helst egentligen, så finns det oftast keyword i språket för att markera om ett attribut eller metod är private, protected eller public. Det finns inga sådana keyword i python. Alla metoder och attribut är som standard publika och kan kommas åt av klasser som ärver. Men det finns en konvention att; om man vill skydda en metod eller attribut i python så namnger man med ett underscore innan.
class Person:
def __init__(self, namn, hemlis):
self.namn = namn
self._hemlis = hemlis
p = Person("Olle", "har en hamster")
print(p.namn)
print(p._hemlis)
class Person:
def __init__(self, namn, hemlis):
self.namn = namn
self._hemlis = hemlis
p = Person("Olle", "har en hamster")
print(p.namn)
print(p._hemlis)
I ovan klass har vi alltså antytt att _hemlis är en protected grej. Men det går fortfarande att snoka! Det här med underscore är bara en indikation att man inte ska röra attributet ifråga - inte något förbud.
Vill du höja nivån av skydd, dvs det som motsvarar private i andra programspråk, så kör du 2 stycken underscore.
class Person:
def __init__(self, namn, hemlis, megahemlis):
self.namn = namn
self._hemlis = hemlis
self.__megahemlis = hemlis
p = Person("Olle", "har en hamster", "kod till lås: 1234")
print(p.namn)
print(p._hemlis)
print(p.__megahemlis)
class Person:
def __init__(self, namn, hemlis, megahemlis):
self.namn = namn
self._hemlis = hemlis
self.__megahemlis = hemlis
p = Person("Olle", "har en hamster", "kod till lås: 1234")
print(p.namn)
print(p._hemlis)
print(p.__megahemlis)
Om du kör ovan så får du ett error. Eller rättare sagt, koden skriver ut namn och _hemlis men därefter får du ett AttributeError. Det går alltså inte få reda på megahemlisen. Dvs, såtillvida man inte är en hacker och känner till att python, för att det skall bli privat, tillämpar namemangling (namn-förvrängning). Vi kan alltså få reda på den privata variabeln ändå, se nedan.
class Person:
def __init__(self, namn, hemlis, megahemlis):
self.namn = namn
self._hemlis = hemlis
self.__megahemlis = megahemlis
p = Person("Olle", "har en hamster", "kod till lås: 1234")
print(p.namn)
print(p._hemlis)
print(p._Person__megahemlis)
class Person:
def __init__(self, namn, hemlis, megahemlis):
self.namn = namn
self._hemlis = hemlis
self.__megahemlis = megahemlis
p = Person("Olle", "har en hamster", "kod till lås: 1234")
print(p.namn)
print(p._hemlis)
print(p._Person__megahemlis)
Men det är mer privat än tidigare. När allt kommer kring, så det här med public, protected och private handlar om att koden ska bra, det är inte på liv och död.
inbyggda klassfunktioner
Klicka för mer exempel hur dessa inbyggda klassfunktioner fungerar.