Det här är inte en lista med facit — det är ett recept. Specen talar om exakt vad du ska skriva. Lär dig översätta "vad specen säger" → "vad du skriver", så löser du uppgifter du aldrig sett förut.
d.get, sorted, s.split(), set-operationer m.m.; guiden säger när.Varje extenta har samma skelett, bara med nya ord (rätter, multiplikationer, bokningar…). Känner du igen formen vet du redan ungefär vad varje uppgift vill ha:
__init__ + ev. __str__. Används av resten.input() som binder ihop allt. Texterna måste matcha exakt.pass, gå vidare, kom tillbaka.Du behöver aldrig "komma på" en lösning. Specen säger redan allt — du översätter bara svenska till kod. Två saker i specen avgör nästan allt: returtypen (pilen ->) och verbet i beskrivningen.
-> ??? först-> int + ordet "antal"→return len(...) eller en räknare-> bool + "om / kontrollera"→return <villkor> (ett True/False-uttryck)-> None + "uppdaterar / lägger till"→ändra self, ingen return-> list + "alla som …"→bygg lista i en loop, return den-> str (ofta __str__)→bygg en f-sträng i exakt rätt format-> KlassNamn→return KlassNamn(...) — skapa ett nytt objekt-> bool vet du att svaret är ja/nej — du behöver inte skriva ut något, inte ändra något, bara return ett villkor.for x in ...:setdict {x: y}listsorted(...)import random + random.choice / shufflemax(d, key=d.get)Står det Egenskaper: högst upp i en klasspec är det en checklista över attribut klassen MÅSTE ha — inget du väljer själv. Testfallen läser dem direkt med objekt.namn, så de ska vara publika (inget understreck) och heta exakt som specen säger.
Ta exemplet från en tenta:
Egenskaper: attempts: int (publikt åtkomlig) Antalet försök. Från början är antalet försök 0. solved_time: int (publikt åtkomlig) Tidpunkten i minuter när uppgiften är löst. Från början är uppgiften olöst och värdet är därför -1.
Läs varje rad i tre delar — namn, typ och startvärde (som ofta gömmer sig i beskrivningen):
attempts→self.attempts — exakt så, publiktint→talar om vad slags värde (här ett heltal)self.attempts = 0self.solved_time = -1def __init__(self): self.attempts = 0 # publikt, startvärde ur texten self.solved_time = -1 # -1 betyder "ännu olöst"
Lägg märke till: ingen av dem skickas in som parameter — de börjar på ett bestämt värde. Startvärdet står nästan aldrig som en siffra i listan, utan i den löpande texten: "från början…", "initialt…", "därför…".
obj.attempts när som helst". Testfallen förlitar sig på det. Stavar du fel (self.attempt) eller gör den privat (self._attempts) hittar testet den inte → 0p, även om logiken är rätt. Att (publikt åtkomlig) står utskrivet är en extra påminnelse om just detta.Egenskaper: → publikt med exakt namn. Allt annat du själv inför för att lösa uppgiften (räknare, hjälp-listor) → privat. Mer om den gränsen i avsnitt 8.Nästan varje klass börjar likadant. Gå igenom de här stegen i ordning, varje gång:
selfStår parametern i konstruktorns signatur? Då sparar du den rakt av:
def __init__(self, namn, pris): self.namn = namn # self.X = X — samma namn, alltid self.pris = pris
self.x = x? Parametern x försvinner när konstruktorn är klar. self.x lever kvar i objektet så att andra metoder kan läsa det senare. self = "det här objektet".Om beskrivningen pratar om något objektet ska "hålla reda på" som inte skickas in, skapar du det tomt. Vilket tomt värde? Det beror på vad det ska göra:
self.x = []self.x = {}self.x = set()self.x = 0self.x = False# Exempel: "håller reda på alla ordrar" + "lediga platser" def __init__(self, total_seats): self.total_seats = total_seats # STEG 1: parameter self.free_seats = total_seats # härledd från parameter self.bookings = set() # STEG 2: tom, "unika bokningar"
Om du måste minnas något om varje element (t.ex. "är den här frågan rätt besvarad?"), skapa en lista lika lång som datan:
def __init__(self, questions): self.questions = questions # datan self._correct = [False] * len(questions) # privat: egen statusflagga
i i båda listorna hör ihop: questions[i] har statusen _correct[i]. Enkelt och räcker långt på tentan.self._correct). Se avsnitt 8.self.items = items — inte self.items = []. Du ska spara det du fått, inte slänga det.Fel datastruktur gör uppgiften svår; rätt gör den nästan trivial. Specens ord avgör — du behöver aldrig gissa:
[]{}set()(a, b)x in lista går igenom alla element (långsamt); x in mängd är direkt (snabbt). Därför står det ibland "för full poäng får inga loopar förekomma" — det är en vink om att använda set/dict istället för att loopa."Koppla bordsnummer till order, men spara också alla ordrar under dagen" → båda behövs:
self._orders = {} # bordsnr → senaste order (kan skrivas över) self._all_orders = [] # historik: varje order någonsin
När du lägger till uppdaterar du båda:
def add_order(self, table, order): self._orders[table] = order # skriver över om bordet fanns self._all_orders.append(order) # läggs alltid till i historiken
Nu kopplar vi ihop allt. Slå upp returtypen i avsnitt 2, välj receptet nedan, fyll i orden från just din uppgift.
# Antal element → len return len(self.items) # Räkna de som uppfyller villkor → räknare i loop n = 0 for x in self.items: if <villkor>: n += 1 return n
Returnera villkoret direkt — skriv aldrig if villkor: return True else: return False.
# Finns elementet? return (name, num) in self.bookings # Gäller det för ALLA? → börja True, sätt False vid motbevis for c in self._correct: if not c: return False return True # kortform: return all(self._correct)
False direkt. Kommer du igenom loopen utan motbevis → True.Ingen return. Du ändrar self (eller en inskickad dict — "in-place").
def add_dish(self, name, price, is_vegan): self.dishes.append(Dish(name, price, is_vegan))
data[prod].append(...) ändrar in-place; data = {...} skapar en ny (fel).result = [] for x in self.items: if <villkor>: result.append(x) return result
Behöver du behålla ursprunglig ordning? Loopa över range(len(...)) så du har index till parallella listor:
for i in range(len(self.items)): if not self._correct[i]: result.append(self.items[i])
__str__)
def __str__(self): if not self.dishes: # specialfall först return "Inga rätter beställda." text = "" for d in self.dishes: text += str(d) + "\n" # en rad per rätt text += f"\nTotalt: {self.total_price()} kr" return text
Återanvänd dina egna metoder istället för att skriva om logiken:
def new_list(self): return MultiplicationList(self.get_incorrect())
# Räkna förekomster i ett dict counts = {} for x in alla: counts[x.name] = counts.get(x.name, 0) + 1 # Den med högst antal (None om tomt) if not counts: return None return max(counts, key=counts.get)
Recepten i avsnitt 6 säger vad returtypen kräver. Men texten under varje metod gömmer ofta två saker till: den refererar tillbaka till egenskaperna (vad betyder "löst"?) och den innehåller nyckelord som blir räkneoperationer. Vi avkodar hela klassen ProblemResult metod för metod.
# attempts: antal försök, börjar på 0 # solved_time: minut då löst, eller -1 om OLÖST ← viktig konvention def __init__(self): self.attempts = 0 self.solved_time = -1
solved_time == -1 betyder "olöst". Metoderna nedan refererar till det utan att upprepa det — du måste komma ihåg definitionen från Egenskaper:.Returtyp bool + "om" → returnera ett villkor. Men hur vet vi att den är löst? Det står inte här — det stod i egenskaperna: löst = solved_time är inte -1.
def is_solved(self) -> bool: return self.solved_time != -1
Egenskaper:. Läs alltid hela specen innan du tolkar en enskild metod.Plocka isär texten mening för mening — varje fras är en kodrad:
if not …: return 0+ ett tillägg20 * (antal ej godkända)attempts - 1def total_time(self) -> int: if not self.is_solved(): # återanvänd metoden ovan! return 0 extra = 20 * (self.attempts - 1) # 20 min per misslyckat försök return self.solved_time + extra
attempts - 1? Är uppgiften löst gjordes det sista försöket rätt — alla innan var misslyckade.self.is_solved() istället för att skriva solved_time != -1 igen. Återanvänd dina egna metoder — det är både kortare och det specen belönar.När en beskrivning är klurig — luta dig mot exemplen. De låser formatet exakt:
"2 -" (två misslyckade)→antal, mellanslag, bindestreck"3 77" (löst på minut 77)→antal, mellanslag, tidpunktif/else på den andra delendef __str__(self) -> str: if self.is_solved(): return f"{self.attempts} {self.solved_time}" # "3 77" return f"{self.attempts} -" # "2 -"
- (inte "ej löst") när det är olöst. "antingen A eller B" → A är alltid med, B avgörs av ett villkor.Egenskaper:) · "om … returneras X" = guard först · "per" = multiplicera · "inklusive/plus" = addera · "antingen … eller" = if/else · exempel låser formatet tecken för tecken · återanvänd egna metoder.self._xEgenskaper: i specen.Egenskaper:→publikt self.x (inget understreck)self._x (ett understreck)booking.free_seats eller game.remaining_words. Allt annat du själv inför för att lösa uppgiften (räknare, hjälp-listor, historik) är klassens interna grejer och ska döljas.# TableBooking: specen listar total_seats, free_seats, bookings # under "Egenskaper:" → alla tre är PUBLIKA def __init__(self, total_seats): self.total_seats = total_seats # publik (egenskap) self.free_seats = total_seats # publik (egenskap) self.bookings = set() # publik (egenskap) # Restaurant: specen listar INGA egenskaper → allt PRIVAT def __init__(self): self._orders = {} # privat (eget val) self._all_orders = [] # privat (eget val)
Använd sedan samma namn (med eller utan _) konsekvent i alla metoder inne i klassen:
def total_sales(self): total = 0 for o in self._all_orders: # _ här också total += o.total_price() return total
add_order, total_sales), inte peta direkt på den interna datan. Då kan du byta ut det inre utan att något utanför går sönder.self._correct, self._used_indexes) står aldrig under "Egenskaper:" → de ska vara privata.Sista pusselbiten binder ihop klasserna med användaren. Receptet är alltid detsamma: fråga → loopa tills klart → skriv slutmeddelande.
input()# Tal? Glöm inte int(...) — input ger alltid en sträng low = int(input("Skriv in den lägsta tabellen: ")) # Flera ord på en rad? .split() delar på mellanslag words = input("Ange fyra ord: ").split()
Använd while not <klar>: — fråga en metod om spelet är slut.
while not game.is_finished(): print("\nKvarvarande ord:") print(sorted(game.remaining_words)) # sortera innan utskrift! words = input("Ange fyra ord: ").split() result = game.guess(words) if result == -1: print("Felaktig inmatning av grupp.") elif result == 4: print("Rätt grupp!") else: print(f"Fel grupp. {result} av fyra var rätt.") print("Alla grupper hittade!")
sum(x.price for x in items)
max(d, key=d.get) # nyckeln max(d.values()) # värdet
sorted(lista) sorted(lista, key=lambda x: x.namn)
d[k] = d.get(k, 0) + 1
d.get(nyckel, 0) # 0 om saknas
a & b # gemensamma a | b # union a - b # differens
x = int(input("…")) ord = input("…").split()
import random
random.choice(lista)
random.shuffle(lista)
[0] * antal # [0, 0, 0]
for i in range(low, high+1): for j in range(i, high+1): # j från i! ...
-> ???) → slå upp receptet i avsnitt 2 & 6.self.x = x; egna egenskaper → tom [] {} set() 0 False.self._x. Bara det som står under "Egenskaper:" är publikt (self.x).pass och gå vidare — delpoäng finns.__str__ och utskrifter: matcha formatet tecken för tecken. "Show Differences".sorted()).None? Ändra self, skriv ingen return.