5.5 DRILL — Klasser med spesialmetoder
Full drill på G-sjangeren: fra oppgavetekst til komplett klasse med de spesialmetodene oppgaven krever, i sensors korte stil.
Dette er drillkapitlet for sjanger G — altså oppgaven «skriv en klasse med spesialmetoder». Med spesialmetode mener vi en metode med to understreker på hver side av navnet, som __init__ eller __call__, og som Python kaller automatisk i bestemte situasjoner. Sjangerbokstavene A til O er bokas kortnavn på de femten oppgavetypene som går igjen på eksamen; G er den som handler om klasser.
- Frekvens: sjanger G er med i 100 % av de åtte gjennomgåtte avsluttende settene.
- Vekt: 8–12 poeng — de tyngste enkeltoppgavene på hele settet.
- Form: nesten alltid flerdelt. Del a) er «skriv klassen», del b) er «bruk den»: instansier, regn ut noen verdier, skriv en testfunksjon eller plott resultatet.
- Prioritet: dette må sitte. Klasser er ett av de fem temaene med høyeste prioritet i faget.
Grunnen til at oppgaven er den sikreste, er at innpakningen roterer, men koden gjør det ikke. Ett år er det en vektor, neste år et polynom, året etter en funksjon med parametre — men det er de samme fem–seks metodene hver gang, og de skrives på under tjue linjer. Målet med kapitlet er at du skal kjenne igjen malen på ti sekunder og skrive den uten å tenke.
Slik er kapitlet lagt opp (~90 min). Først løsningsoppskriften og de fire feilene som koster mest (~15 min), så ett gjennomarbeidet eksamenscase med margnotater om hva som gir uttelling ved hvert steg (~20 min), og til slutt tolv oppgaver på eksamensnivå (~55 min). Det er to naturlige pausepunkter underveis — du trenger ikke ta alt i én økt.
Forkunnskaper — sist du var her
Drillen forutsetter hele Del 5: kap. 5.1 (konstruktør og kallbar instans), kap. 5.2 (utskrift og aritmetikk), kap. 5.3 (arv) og kap. 5.4 (stykkvise funksjoner). Fra resten av boka trenger du funksjoner og standardverdier (kap. 1.6), f-strenger (kap. 1.4), løkker (kap. 1.3), testfunksjoner (kap. 3.1) og tabeller og plotting (kap. 4.1 og kap. 4.3).
Her er de to konstruksjonene du kommer til å skrive flest ganger i dette kapitlet, friskt oppfrisket.
1. Funksjonsklassen. Konstruktøren tar det som er fast, kallmetoden tar det som varierer:
from math import exp
class Gauss:
def __init__(self, m, s):
self.m = m
self.s = s
def __call__(self, x):
m, s = self.m, self.s
return exp(-(x - m)**2/(2*s**2))
g = Gauss(0, 1)
print(g(0), g(1))Utskrift:
1.0 0.60653065971263342. Aritmetikk som gir en ny instans. Plusstegnet mellom to objekter er et metodekall, og metoden skal levere et nytt objekt av samme klasse:
class Vind:
def __init__(self, ost, nord):
self.ost = ost
self.nord = nord
def __str__(self):
return f'({self.ost}, {self.nord})'
def __add__(self, other):
return Vind(self.ost + other.ost, self.nord + other.nord)
a = Vind(3, 4)
b = Vind(-1, 2)
print(a + b)
print(a)Utskrift:
(2, 6)
(3, 4)Legg merke til den siste linja: a er uendret. Aritmetikk lager et tredje objekt og lar operandene være i fred, akkurat som 3 + 4 ikke endrer tretallet.
Les oppgaveteksten én gang med blyanten i hånda, og strek under hvert krav. Gjør så dette, i rekkefølge. Hvert steg svarer til ett spørsmål du besvarer ved å se på oppgaveteksten, ikke ved å tenke selv.
1. class Navn: — hva heter klassen? Navnet står nesten alltid ordrett i oppgaveteksten, og du skal bruke akkurat det navnet. Stor forbokstav.
2. __init__ lagrer alt som er fast. Hvilke størrelser er gitt én gang, når objektet lages? De blir parametre i konstruktøren og lagres som attributter: self.a = a. Har oppgaven en standardverdi («med hvis ikke annet er oppgitt»), skriver du den i signaturen: def __init__(self, f, h=1e-5):.
3. __call__ regner ut funksjonsverdien. Hvilken størrelse varierer fra kall til kall? Den blir parameter i kallmetoden. Skal objektet kunne brukes som en vanlig funksjon — «slik at f(2) gir funksjonsverdien» — er det __call__ oppgaven ber om.
4. __str__ hvis oppgaven vil se objektet. Formuleringer som «slik at print(p) skriver …» eller «en pen utskrift av polynomet» betyr __str__, og den skal returnere en f-streng.
5. __add__ og __mul__ hvis oppgaven bruker + eller * mellom objekter. De returnerer en ny instans av klassen. Eneste unntak: multiplikasjon som er definert som et indreprodukt returnerer et tall, og da skiller du de to tilfellene med isinstance.
6. Arv når to klasser deler kode. Sier oppgaven at den nye klassen er «et spesialtilfelle av» eller «som forrige, men med …», skriver du class Sub(Base): og lar super().__init__(...) være første linje i den nye konstruktøren.
7. Del b): instansier og bruk. Lag objektet med de tallene oppgaven oppgir, og gjør det oppgaven ber om — skriv ut noen verdier, lag en testfunksjon med assert abs(fasit - beregnet) < tol, eller lag et punktgitter og plott. Denne delen kan løses selv om du ikke fikk til del a).
Formen på svaret. Hele besvarelsen skal være kort: fem–tjue linjer, ingen kommentarer utenom der du dokumenterer en antakelse, ingen ekstra utskrift og intet hovedprogram. Sensor leter etter strukturen, ikke etter volum.
self-en. Feilkode #3 i bokas feilregister dekker to varianter: self som mangler i signaturen (def __call__(x):) og self. som mangler foran et attributt inne i metoden (return a*x der det skulle stått self.a*x). Den første gir en feilmelding med et merkelig argumenttall; den andre gir NameError. Fast plantet felle i «finn feilen»-oppgaver.#4 — __add__ som returnerer feil type. Å skrive return self.x + other.x, self.y + other.y gir et tuppel, ikke et objekt. Programmet ser ut til å virke helt til noen skriver (u + v)*2 eller print(u + v) — og da kommer feilen et helt annet sted i koden enn der årsaken er. Skriv alltid return Klassenavn(...).
Blandede argumentlister. Å legge en parameter i __init__ som egentlig varierer fra kall til kall, eller motsatt. Testen er enkel: hvis to kall på samme objekt skal gi ulikt svar, hører størrelsen i __call__.
Glemt super().__init__(...). Subklassen ser riktig ut, men attributtene blir aldri satt, og første kall gir AttributeError. Kallet skal stå som første linje i subklassens konstruktør, og du sender ikke med self i kallet.
En femte felle, som ikke gir feilmelding i det hele tatt: __str__ uten return. En metode som når slutten uten return, leverer None, og da får du TypeError: __str__ returned non-string (type NoneType) — en melding som peker på riktig metode, men bare hvis du vet hva den betyr.
Det gjennomarbeidede caset (~20 min)
Under står en komplett, tredelt oppgave i sjanger G, av samme type og vekt som på en avsluttende eksamen. Les oppgaveteksten, prøv deg på del a) før du ser videre, og les så modellbesvarelsene med margnotatene om hva som gir uttelling.
> Oppgave (10 poeng). En dempet svingning — for eksempel utslaget til en fjærbelastet masse i en væske — beskrives av
>
>
>
> der er startutslaget, er dempingen og er vinkelfrekvensen.
>
> a) Skriv en klasse Dempesvingning der , og gis når objektet lages, der s(t) gir utslaget ved tiden , og der print(s) skriver formelen med tallene satt inn. (5 poeng)
>
> b) Lag en instans med , og . Skriv en testfunksjon som kontrollerer verdien i , og skriv ut en tabell over utslaget for . (3 poeng)
>
> c) En udempet svingning er tilfellet . Skriv en klasse Udempet som arver fra Dempesvingning og bare tar og . (2 poeng)
Skriv Dempesvingning med konstruktør, kallmetode og utskriftsmetode.
Gå gjennom oppskriften: klassenavnet står i teksten (steg 1); , og er gitt når objektet lages, altså faste (steg 2); varierer fra kall til kall, altså __call__ (steg 3); «print(s) skriver formelen» betyr __str__ (steg 4). Ingen + eller * mellom objekter, så steg 5 og 6 er ikke aktuelle her.
from math import exp, cos
class Dempesvingning:
def __init__(self, A, b, w):
self.A = A
self.b = b
self.w = w
def __call__(self, t):
return self.A*exp(-self.b*t)*cos(self.w*t)
def __str__(self):
return f'{self.A}*exp(-{self.b}*t)*cos({self.w}*t)'
s = Dempesvingning(2.0, 0.5, 3.0)
print(s)
print(s(0))
print(s(1))Utskrift:
2.0*exp(-0.5*t)*cos(3.0*t)
2.0
-1.2009216041472504Hva gir uttelling, steg for steg (5 poeng):
- 1 poeng: class Dempesvingning: med __init__ som tar de tre parametrene. Selve rammeverket. Får du bare dette, har du ett poeng.
- 1 poeng: de tre self.-tilordningene. Skriver du A = A i stedet for self.A = A, mister du dette poenget og alt som bygger på det — det er feil #3.
- 2 poeng: __call__ med riktig formel. Selve kjernen. Bruker du ** riktig, har fortegnet i eksponenten på plass og ganger de to faktorene sammen, er poenget ditt. Bytter du cos med sin, mister du ett halvt — strukturen er riktig.
- 1 poeng: __str__ som returnerer en f-streng. Den eksakte formateringen er fri; sensor krever ikke at parentesene står nøyaktig som her, bare at det er en streng og at tallene er med.
Merk at det greske i formelen heter w i koden. Det er helt vanlig og fullt akseptert: greske bokstaver skrives ut med latinske bokstaver i Python, og w for omega er standard i faget. Merk også at klassen kalles med s(1), mens print(s) skriver teksten — samme objekt, to helt forskjellige metoder.
Instansier klassen, kontroller den med en testfunksjon, skriv verditabellen — og lag subklassen for den udempede svingningen.
from math import exp, cos
class Dempesvingning:
def __init__(self, A, b, w):
self.A = A
self.b = b
self.w = w
def __call__(self, t):
return self.A*exp(-self.b*t)*cos(self.w*t)
def test_dempesvingning():
s = Dempesvingning(2.0, 0.5, 3.0)
expected = 2.0
computed = s(0)
tol = 1e-10
assert abs(expected - computed) < tol, 'feil i t = 0'
test_dempesvingning()
s = Dempesvingning(2.0, 0.5, 3.0)
for i in range(5):
t = 0.5*i
print(f'{t:4.1f} {s(t):8.4f}')Utskrift:
0.0 2.0000
0.5 0.1102
1.0 -1.2009
1.5 -0.1991
2.0 0.7065Hva gir uttelling (3 poeng): 1 poeng for instansieringen med riktige tall, 1 for testfunksjonen (uten argumenter, med abs(...) < tol og ikke ==), 1 for tabellen. At tabellen har fem linjer og ikke fire er av-én-regelen igjen: fra 0 til 2,0 med steg 0,5 er fire steg og fem punkter, altså range(5).
— naturlig pausepunkt —
Del c). Den udempede svingningen er nøyaktig samme formel med . Det er den klassiske arvesituasjonen: subklassen har færre parametre, ikke flere, og fyller resten inn selv.
from math import exp, cos
class Dempesvingning:
def __init__(self, A, b, w):
self.A = A
self.b = b
self.w = w
def __call__(self, t):
return self.A*exp(-self.b*t)*cos(self.w*t)
def __str__(self):
return f'{self.A}*exp(-{self.b}*t)*cos({self.w}*t)'
class Udempet(Dempesvingning):
def __init__(self, A, w):
super().__init__(A, 0.0, w)
def __str__(self):
return f'{self.A}*cos({self.w}*t)'
u = Udempet(2.0, 3.0)
print(u)
print(u(0), u(1))
print(isinstance(u, Dempesvingning))Utskrift:
2.0*cos(3.0*t)
2.0 -1.9799849932008908
TrueHva gir uttelling (2 poeng): 1 poeng for class Udempet(Dempesvingning): med riktig parameterliste, 1 for super().__init__(A, 0.0, w) med nullen på riktig plass. Den overstyrte __str__-en er en bonus og ikke krevd — uten den arves basisklassens versjon, som skriver 2.0*exp(-0.0*t)*cos(3.0*t). Det er ikke galt, bare mindre pent.
Margnotat om delvis uttelling. De to poengene i del c) er uavhengige av del a) og b). Skriver du subklassen riktig, får du poengene selv om __call__ i basisklassen var feil. Det er derfor du alltid skal skrive noe på hver deloppgave: å få alle detaljer 100 % riktig under tidspress er nesten umulig, og poengene er lagt opp etter det.
Oppgaver: samme mal, ny innpakning (~25 min for oppgave 1–6)
Alle oppgavene under er nyskrevne og på eksamensnivå. De roterer klassetypene systematisk: funksjonsklasse, klasse som pakker inn en annen funksjon, vektorklasse med aritmetikk, klasse med rekurrent formel, arvepar og stykkvis klasse — pluss sporingsoppgaver som tester at du vet hvilken metode som kjøres når. Skriv løsningene for hånd, uten å kjøre koden. Det er slik eksamen er.
(Innstegsoppgave, midtveisnivå, sjanger A — kodesporing, altså «hva skriver dette programmet ut?».) Skriv utskriften nøyaktig, med mellomrom og linjeskift slik terminalen viser den.
class Teller:
def __init__(self, start):
self.n = start
print('init', self.n)
def __call__(self, k):
self.n = self.n + k
return self.n
t = Teller(4)
print(t(1))
print(t(1))
print(t.n)der er substratkonsentrasjonen, er den høyeste hastigheten og er den konsentrasjonen som gir halv makshastighet.
a) Skriv en klasse Michaelis der og gis når objektet lages, og der v(S) gir hastigheten.
b) Lag en instans med og , og skriv ut hastigheten for , og .
c) Hva er den matematiske grunnen til at verdien i er nøyaktig halvparten av ?
(Midtveisnivå, sjanger A — kodesporing.) Hva skriver programmet ut?
class Prove:
def __init__(self, navn, ph):
self.navn = navn
self.ph = ph
def __str__(self):
return f'{self.navn}: pH = {self.ph:.2f}'
p = Prove('Bekk 1', 6.7)
q = Prove('Bekk 2', 7.25)
print(p)
print(str(q) + '!')
print([p.navn, q.ph])a) Skriv en klasse Forlengs som tar funksjonen f og steget h med standardverdi når objektet lages, og der kallet d(x) gir den forlengs deriverte.
b) Lag en instans for eksponentialfunksjonen, og skriv ut den deriverte i sammen med den eksakte verdien.
c) Lag en instans til med , og forklar hva den ekstra utskriften viser.
En vindmåling har en østkomponent og en nordkomponent, begge i meter per sekund.
a) Skriv en klasse Vind med __str__ på formen (3, 4) m/s, __add__ som legger sammen komponentvis, og __mul__ som gir indreproduktet når høyre operand er en Vind, og en skalert vind når den er et tall.
b) Legg til en vanlig metode fart som gir farten .
c) Vis bruken: summen av to vindvektorer, indreproduktet, en dobling og farten til den første.
(Midtveisnivå, sjanger A — kodesporing.) Hva skriver programmet ut?
class Vind:
def __init__(self, ost, nord):
self.ost = ost
self.nord = nord
def __str__(self):
return f'({self.ost}, {self.nord})'
def __add__(self, other):
print('legger sammen')
return Vind(self.ost + other.ost, self.nord + other.nord)
a = Vind(1, 2)
b = Vind(3, 4)
c = a + b + a
print(c)
print(a)Diff-mønsteret fra kap. 5.1, og det kommer igjen i Del 6 om numerisk derivasjon.Oppgave 3 og 6 var sporing av utskrift og aritmetikk. Bommet du på 6.70 i oppgave 3 eller på antall «legger sammen»-linjer i oppgave 6, er det formaterings- og kjedingsdetaljene som må drilles, ikke klasseforståelsen.
Oppgave 5 var den store: åtte poeng, fire metoder pluss en vanlig metode. Den er malen for hele vektorfamilien på eksamen. Klarte du __add__ og __mul__ med riktig returtype, kan du regne med at du har den delen av sjanger G som er verdt mest.
Oppgave 7–12: arv, rekurrente formler og feilsøking (~30 min)
— naturlig pausepunkt —
De neste seks oppgavene er tyngre. To av dem er arv, én kombinerer klasse med en rekurrent formel, én er «finn feilen», og de to siste er en full flerdelt eksamensoppgave og et flervalg av typen «hvilken linje mangler». Ta dem gjerne som en egen økt.
a) Skriv en klasse Cheb der graden gis når objektet lages, der kallet t(x) gir regnet ut med en løkke, og der print(t) skriver T_3(x) for grad 3.
b) Skriv en testfunksjon som kontrollerer klassen for mot det kjente uttrykket i punktet .
c) Skriv ut , og , og kontroller den midterste i hodet.
Hastigheten til en kjemisk reaksjon av orden er , der er konsentrasjonen og er hastighetskonstanten.
a) Skriv en klasse Reaksjon der og gis når objektet lages, der r(c) gir hastigheten, og der print(r) skriver formelen med tallene satt inn.
b) En førsteordens reaksjon er tilfellet . Skriv en subklasse ForsteOrden som bare tar .
c) Gi subklassen en metode halveringstid som returnerer , og vis at et ForsteOrden-objekt fortsatt regnes som en Reaksjon.
Programmet under skal representere en saltblanding: __str__ skal beskrive den, + skal blande to porsjoner, og kallet b(x) skal gi hvor mange gram salt det er i x gram av blandingen. Finn alle feilene, forklar hva hver av dem gjør, og skriv programmet riktig.
class Blanding:
def __init__(self, salt, vann):
self.salt = salt
self.vann = vann
def __str__(self):
f'{self.salt} g salt i {self.vann} g vann'
def __add__(self, other):
return self.salt + other.salt, self.vann + other.vann
def __call__(x):
return salt/(salt + vann)*x
a = Blanding(5, 95)
b = Blanding(15, 85)
print(a + b)
print((a + b)(200))(Midtveisnivå, sjanger A — kodesporing.) Klassen under er den generelle stykkvise funksjonen fra kap. 5.4. Hva skriver programmet ut?
class Tariff:
def __init__(self, a, b):
self.a = a
self.b = b
def __call__(self, x):
for i, b_ in enumerate(self.b):
if x < b_:
return self.a[i]
return self.a[-1]
t = Tariff([0.5, 1.2, 2.0], [100, 400])
print(t(50), t(100), t(399), t(400), t(1000))der er temperaturen i kelvin, er løseligheten ved referansetemperaturen , og er en stoffavhengig konstant.
a) Skriv en klasse Loslighet der og gis når objektet lages, der har standardverdien 298,0, der s(T) gir løseligheten, og der print(s) skriver formelen med tallene satt inn.
b) Skriv en testfunksjon som kontrollerer at objektet gir nøyaktig ved .
c) Lag en instans med og , og skriv ut løseligheten ved 273,0 K, 298,0 K og 323,0 K med fire desimaler.
d) Skriv koden som plotter to salter i samme figur — og , begge med — for 81 punkter fra 273 K til 353 K, med legende og navngitte akser. Beskriv figuren i ord.
(Midtveisnivå, sjanger E — «hvilken linje mangler?». Sjanger E er flervalgstypen der du skal peke ut den ene linja eller det ene kallet som gjør at programmet virker.) Klassen under skal gjøre at print(Fart(90)) skriver 90 km/t, men den skriver i stedet noe slikt som <__main__.Fart object at 0x104e3a1f0>. Velg ett svar.
class Fart:
def __init__(self, v):
self.v = v
def tekst(self):
return f'{self.v} km/t'
print(Fart(90))a) print må byttes til print(Fart(90).tekst)
b) self.v = v må byttes til v = v
c) Metoden må hete __str__ i stedet for tekst
d) Klassen mangler en __call__-metode
super()-kallet.Oppgave 9 var feilsøking, og den viktigste lærdommen der er at feilen dukker opp et helt annet sted enn der årsaken står. Oppgave 10 testet grensen i en stykkvis funksjon — det ene punktet der < og <= gir forskjellig svar.
Oppgave 11 var settets tunge oppgave, med fire deler og tolv poeng. Legg merke til at bare fire av dem lå i selve klassen: resten lå i testfunksjonen, formateringen og plottet. Det er den vanligste grunnen til at studenter taper poeng på sjanger G — de bruker all tiden på del a) og rekker ikke resten. Oppgave 12 var det billige poenget: to sekunders gjenkjenning hvis du vet hvilken metode print leter etter.
Begrepsbank
Begrepsbanken er flashcard-/repetisjonsstoff — den gjentar det du nettopp har lest. Hopp trygt over ved førstegangslesing; tidsanslaget for kapitlet gjelder kjernestoffet.
Oppgaven «skriv en klasse med spesialmetoder». Den forekommer i 100 % av de åtte gjennomgåtte avsluttende settene og er verdt 8–12 poeng — de tyngste enkeltoppgavene på settet.
Innpakningen roterer år for år: vektor, polynom, funksjon med parametre, stykkvis funksjon. Koden gjør det ikke. Det er de samme fem–seks metodene hver gang, på under tjue linjer.
Klassenavnet står nesten alltid ordrett i oppgaven («skriv en klasse Michaelis …»), og du skal bruke akkurat det navnet, med stor forbokstav.
Sensor leser koden med oppgaveteksten ved siden av. Et annet navn tvinger fram ekstra lesing og gjør det vanskeligere å se at du har løst oppgaven.
Alt som gis én gang, når objektet lages, hører i __init__ og lagres som attributt med self.navn = navn. Standardverdier står i signaturen: def __init__(self, f, h=1e-5):.
Testen: skal to kall på samme objekt kunne gi ulikt svar? Da hører størrelsen ikke her.
Formuleringer som «slik at f(2) gir funksjonsverdien» eller «objektet skal kunne brukes som en vanlig funksjon» betyr __call__. Parameteren er den størrelsen som endrer seg fra kall til kall.
Uten __call__ gir obj(3) feilmeldingen «object is not callable».
«Slik at print(p) skriver …» betyr __str__. Metoden tar ingen argumenter utenom self og skal returnere en streng.
Glemmer du return, leverer metoden None, og Python svarer TypeError: __str__ returned non-string (type NoneType). Feilmeldingen peker på riktig metode.
Brukes + eller * mellom to objekter, skal __add__ og __mul__ returnere et nytt objekt av klassen: return Klasse(...). Operandene skal være urørt etterpå.
Eneste unntak: multiplikasjon definert som indreprodukt gir et tall. De to tilfellene skilles med isinstance(other, Klasse).
Formuleringer som «som forrige klasse, men med …» eller «et spesialtilfelle av» betyr class Sub(Base):. Subklassen har typisk færre parametre og fyller resten inn selv.
super().__init__(...) står som første linje i subklassens konstruktør, og du sender ikke med self i kallet.
Siste del av oppgaven er alltid bruk: lag objektet med tallene som er oppgitt, skriv ut noen verdier, lag en testfunksjon, eller lag et punktgitter og plott.
Denne delen er uavhengig av del a) og gir poeng selv om klassen ikke ble helt riktig. Den er også den vanligste grunnen til at studenter taper poeng: de bruker all tiden på klassen.
Spørsmålet som avgjør om en oppgave skal løses med klasse eller med en vanlig funksjon: er det én ting med parametre som skal brukes mange ganger?
Er svaret ja — en funksjon med to–tre konstanter som skal evalueres i mange punkter — er klassen riktig. Er svaret nei, holder en vanlig funksjon. På eksamen sier oppgaveteksten det uansett, men testen hjelper deg å huske hva som hører hvor.
Samme mal som for en vanlig funksjon, med instansieringen inne i testen:
def test_klasse():
obj = Klasse(2.0, 0.5)
expected = 2.0
computed = obj(0)
tol = 1e-10
assert abs(expected - computed) < tol, 'melding'Velg et punkt der svaret er eksakt — typisk der en eksponent blir null eller et ledd faller bort. Da tåler du en stram toleranse. Testfunksjonen tar ingen argumenter og skriver ikke ut noe.
En klasse kan ha helt vanlige metoder ved siden av spesialmetodene: fart, halveringstid, areal. De defineres som def fart(self): og kalles med navn og parentes: a.fart().
Forskjellen fra et attributt er parentesen. a.ost er en lagret verdi; a.fart() regner ut noe.
En formel som definerer hvert ledd ut fra de foregående, som , løses med løkke og to variabler som holder de to siste verdiene.
Rekkefølgen er kritisk: regn ut den nye verdien først, skyv så variablene ett hakk. Rekursjon — at metoden kaller seg selv — er utenfor pensum i dette faget og markeres uønsket i fasit.
Eksamen er hjelpemiddelfri, så klassen skrives i ett gjennomtrekk uten å testes. Vanen som gjør det mulig: skriv metodesignaturene først — __init__, __call__, __str__ — og fyll inn kroppene etterpå.
Da glemmer du aldri self, og du ser med én gang om du har lagt en størrelse i feil metode.
Poengene i en klasseoppgave er fordelt på strukturen, ikke på plettfrihet. Klasseramma, self.-tilordningene, hver spesialmetode og bruken teller hver for seg.
Det betyr at en klasse med riktig oppsett og én fortegnsfeil i formelen får det aller meste av poengene, og at deloppgavene kan løses uavhengig. Skriv derfor noe på hver del.
Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.
Skolesaga er en uavhengig læringsressurs og er ikke tilknyttet eller godkjent av Universitetet i Oslo. Dette er ikke offisielt studiemateriell. Les mer.