Se lecture 2
Pausa vid kodexemplen och försök förutsäga hur många gånger varje rad körs.
Öppna Harvard vecka 2 ↗Lektion 2 · Cirka 45 min genomgång
En loop upprepar ett kodblock. En samling håller flera värden tillsammans. När de kombineras kan samma tydliga instruktion bearbeta många värden.
Här går variabeln namn igenom listans värden, ett i taget. Varje varv kallas en iteration.
namnlista = ["Ada", "Grace", "Guido"]
for namn in namnlista:
print(f"Hej {namn}!")Hej Ada!Hej Grace!Hej Guido!Före genomgången
Harvards lecture 2 handlar om Loops. Se filmen före lektionen och använd denna sida som svensk genomgång och uppslagsverk. Vi bygger vidare på funktioner, villkor, strängar och booleska uttryck från lektion 0 och 1.
Pausa vid kodexemplen och försök förutsäga hur många gånger varje rad körs.
Öppna Harvard vecka 2 ↗Skapa lektion_02 i kursmappen och öppna den i VS Code.
Skriv ned variablernas värden efter varje iteration innan du kör programmet.
Använd while när upprepningen styrs av ett villkor och du inte säkert vet antalet varv. Använd for när du vill gå igenom värden i en itererbar följd, exempelvis en lista, en sträng eller ett range-objekt.
Dagens karta
Varje nytt verktyg får en tydlig uppgift, syntax och teststrategi.
8 min
8 min
8 min
8 min
7 min
6 min
Upprepa så länge
while testar ett villkor före varje varvEn iteration är ett genomfört varv i en loop. En while-loop utvärderar sitt booleska villkor före varje iteration och kör det indragna kodblocket så länge villkoret är True.
En räknare är en variabel som följer hur långt loopen har kommit. I exemplet börjar i på 0. Operatorn += betyder ”ta det nuvarande värdet, addera och tilldela resultatet tillbaka”; i += 1 är alltså en kortform av i = i + 1.
När i blir 3 är villkoret i < 3 falskt och loopen avslutas. Eftersom 3 inte ingår körs varven för 0, 1 och 2. Detta mönster — börja på 0 och gå fram till men inte med en stoppgräns — återkommer i Python.
i = 0
while i < 3:
print(i)
i += 1012Om i += 1 saknas förändras aldrig villkoret och loopen blir oändlig. Om du använder fel gräns eller <= i stället för < kan loopen gå ett varv för mycket — ett så kallat off-by-one-fel.
while True skapar avsiktligt ett villkor som alltid är sant. Loopen behöver därför en annan tydlig väg ut. break avslutar den när inmatningen är godkänd. En tom sträng är falsy, så if namn: är sant när användaren har skrivit minst ett tecken.
input returnerar alltid en sträng. Om du skriver int(input(...)) och användaren matar in något som inte kan bli ett heltal uppstår ValueError. Hur sådana undantag fångas kommer i nästa avsnitt.
while True:
namn = input("Namn: ").strip()
if namn:
break
print(f"Hej, {namn}!")Hej, Ada!Ett värde i taget
for går igenom en itererbar följdEtt itererbart objekt är något Python kan lämna ett element i taget från, exempelvis en sträng, en lista eller ett range-objekt. I varje iteration binds loopvariabeln till nästa värde.
for _ in range(3):
print("mjau")mjaumjaumjaurange skapar heltalsföljdenrange returnerar ett särskilt itererbart range-objekt. Det lagrar inte en färdig lista med alla tal, utan beskriver hur talen ska produceras. Stoppvärdet ingår aldrig.
range(stop)stop: range(3) ger 0, 1, 2.range(start, stop)start och stannar före stop.range(start, stop, steg)steg varje varv; steget kan även vara negativt._range(2, 6)for tal in range(2, 6):
print(tal, end=" ")2 3 4 5Stoppvärdet 6 ingår inte.
range(10, 0, -2)for tal in range(10, 0, -2):
print(tal, end=" ")10 8 6 4 2Ett negativt steg gör följden fallande; 0 ingår inte.
for uttrycker ”för varje värde i denna följd”. while uttrycker ”så länge detta villkor är sant”. Båda kan ibland lösa samma problem, men den struktur som gör stoppregeln tydligast är lättare att läsa och testa.
Flera värden i ordning
En lista samlar noll eller flera element mellan hakparenteser. Den är ordnad, så varje element har en bestämd position, och muterbar, vilket betyder att innehållet kan ändras efter att listan skapats.
Ett index är ett heltal som anger en position. Det första elementet har index 0, det andra index 1 och så vidare. Ett negativt index räknar bakifrån: -1 är sista elementet och -2 det näst sista.
Listor kan innehålla olika datatyper, även andra listor. För tydliga program brukar elementen ändå representera samma slags sak. Ett index utanför listan ger IndexError.
0Ada1Grace2Guido-1Guidonamn = ["Ada", "Grace", "Guido"]
print(namn[0])
print(namn[-1])AdaGuidoEn slice är ett utsnitt av en sekvens och skrivs lista[start:stop:steg]. Startpositionen ingår, stopp-positionen ingår inte. Delar som utelämnas får rimliga standardvärden: början, slutet eller steg 1.
namn[1:3]namn[:2]namn[::2]namn[::-1]namn = ["Ada", "Grace", "Guido", "Margaret"]
urval = namn[1:3]
print(urval)['Grace', 'Guido']Samma princip gäller för range och slices. Det gör att längden på lista[start:stop] normalt är stop - start och minskar risken för gränsfel.
Läs, ändra och gå igenom
En metod är en funktion som hör till ett objekt och anropas med punktnotation. Eftersom listor är muterbara kan vissa listmetoder ändra samma lista direkt.
append, pop, sortappend(värde) lägger till sist. pop() tar bort och returnerar sista elementet; med ett index tas den positionen bort. sort() sorterar samma lista och returnerar None.
sorted och slicessorted(lista) returnerar en ny sorterad lista och lämnar originalets ordning orörd. En slice, till exempel lista[:], skapar också en ny yttre lista.
namn = ["Guido", "Ada"]
namn.append("Grace")
alfabetisk = sorted(namn)
print(alfabetisk)
print(namn)['Ada', 'Grace', 'Guido']['Guido', 'Grace', 'Ada']När du behöver själva elementen kan loopen läsa dem direkt. len(namn) returnerar antalet element, men for i in range(len(namn)) behövs främst när positionen ska användas. enumerate(namn) ger både index och element som par.
Ett sådant par är en tupel: en ordnad, vanligtvis oföränderlig sekvens. I for i, namn in enumerate(...) sker uppackning — parets två värden binds till varsitt namn.
for namn in namnlista:
print(namn)Välj detta när positionen inte behövs.
enumeratefor i, namn in enumerate(namnlista, start=1):
print(i, namn)start=1 påverkar numreringen, inte listans index.
Efter b = a är a och b alias för samma listobjekt; en ändring via det ena namnet syns via det andra. b = a.copy() skapar en ny yttre lista. För nästlade listor delas fortfarande de inre objekten — en fullständig oberoende kopia kräver exempelvis copy.deepcopy.
Nyckel möter värde
Typen dict är en muterbar avbildning från unika nycklar till värden. Namnet är en förkortning av dictionary, men vi använder Pythons exakta namn dict. I stället för ett positionsindex hämtar du ett värde med dess nyckel.
I student["namn"] är "namn" nyckeln och "Ada" det tillhörande värdet. Samma nyckel kan bara förekomma en gång; en ny tilldelning till samma nyckel ersätter värdet.
Operatorn in testar medlemskap. För en dict testar den nycklar: "kurs" in student. Ett uppslag med en saknad nyckel ger KeyError, medan student.get("kurs") normalt returnerar None.
None är Pythons särskilda värde för att något saknas. Det skrivs utan citattecken och är inte samma sak som strängen "None".
student = {
"namn": "Ada",
"kurs": "Python",
}
print(student["namn"])
for nyckel, varde in student.items():
print(f"{nyckel}: {varde}")Adanamn: Adakurs: Pythonitems() ger parMetoden items() ger varje nyckel och dess värde tillsammans som en tupel. Loopen packar upp paret i nyckel och varde. Om du bara skriver for nyckel in student får du nycklarna.
Komplexa data byggs genom att kombinera enkla strukturer. Här är studenter en lista, varje element har typen dict och beskriver en student. Uttrycket student["namn"] hämtar namnet från det dict-objekt som loopvariabeln för tillfället pekar på.
studenter = [
{"namn": "Ada", "kurs": "Python"},
{"namn": "Grace", "kurs": None},
]
for student in studenter:
print(student["namn"], "—", student["kurs"])Ada — PythonGrace — NoneKontroll över varven
break, continue och nästlade looparbreak avslutar den närmaste loopen. continue hoppar över resten av den aktuella iterationen och fortsätter med nästa. return är annorlunda: det avslutar hela funktionsanropet och kan lämna ett returvärde.
for tal in range(1, 7):
if tal % 2 == 0:
continue
print(tal)
if tal == 5:
break135Jämna tal möter continue, så utskriften och det senare villkoret hoppas över för just det varvet. När talet är 5 sker utskriften först och därefter avslutar break loopen. En break lämnar alltså inte bara en if-sats; den lämnar den loop som omger satsen.
En loop kan ha en else-del. Den körs om loopen avslutas normalt, men inte om den avbryts med break. Detta är användbart vid sökning men är en fördjupning — en boolesk hjälpvariabel kan ibland vara tydligare.
För varje iteration i den yttre loopen genomför den inre loopen alla sina iterationer. Om båda kör tre varv blir det sammanlagt 3 × 3 = 9 utskrifter. break påverkar bara den närmaste, alltså innersta, loopen.
En sträng är också itererbar. Därför kan övningar som camelCase och Just setting up my twttr gå igenom texten tecken för tecken och använda medlemskapstestet in.
for rad in range(3):
for kolumn in range(3):
print("#", end="")
print()#########zipzip(a, b) parar ihop element på motsvarande positioner och ger ett itererbart zip-objekt. Det stannar när den kortaste följden tar slut. Objektet förbrukas när det itereras; vill du återanvända paren kan du först skapa list(zip(a, b)).
Problem Set 2
Harvards aktuella uppgiftssida är kravspecifikationen. Äldre lokala lösningar kan avvika och ska inte användas som facit.
Gå igenom tecknen i ett camelCase-namn. När ett tecken är versal ska en understrykning och motsvarande gemen skrivas.
isupper() och lower() används.name, firstName och preferredFirstName.Upprepa inmatning tills 50 cent har betalats. Acceptera bara mynten 25, 10 och 5 och skriv återstående belopp efter varje giltigt mynt.
Ta bort vokalerna A, E, I, O och U ur text, oberoende av skiftläge, men behåll övriga tecken.
Skriv funktionen is_valid som kontrollerar längd, inledande bokstäver, sifferordning och att alla tecken är alfanumeriska.
Normalisera ett fruktnamn och slå upp kalorimängden i en dict. Om frukten saknas ska programmet inte skriva något.
Lista normalfall, gränsfall och ogiltig inmatning innan du kodar.
Vad ändras varje varv och exakt när ska loopen stanna?
Kör ofta och läs felmeddelandet från första raden.
Kontrollera tomt, kort, långt, okänt och värden precis vid gränserna.
Repetition och källor
Denna svenska genomgång följer kursens notebook, videoföreläsningen och Harvards aktuella vecka 2. Använd alltid uppgiftssidan för den senaste formuleringen av kraven.
Din slutkontroll
✓ Jag kan välja mellan while och for.
✓ Jag kan förklara varför stoppvärdet inte ingår i range eller en slice.
✓ Jag kan skilja element, index, nyckel och värde.
✓ Jag vet vilka listoperationer som ändrar listan.
✓ Jag kan förklara break, continue och return.
✓ Jag testar loopens stoppregel och alla gränsfall.