3. Listor och Anrop

Programmeringsteknik

Hoppa till: navigering, sök
       Teori          Mer om listor          Övningar      


Innehåll

Listor

Oftast är den som skriver ett program (dvs programmeraren) inte den som kommer att använda det. Den som skriver programmet har kunskap om programmering men man ställer inga krav om kunskap i programmering för den som ska använda programmet. Detta gör att programmeraren måste skriva programmet på ett sätt så att den kan köras av olika användare med olika förväntningar.

Antag att vi vill skriva ett program som ska läsa in fem stycken namn och när man har matat in alla fem namnen skrivs de ut i omvänd ordning (dvs sista namnet först).

Med den programmeringskunskap du har idag är detta fullt möjligt. Det är bara att använda sig av fem olika variabler för att lagra namnen och sedan skriva ut dem i omvänd ordning, som programmet nedan.

namn1 = input("Ange ett namn: ")
namn2 = input("Ange ett namn: ")
namn3 = input("Ange ett namn: ")
namn4 = input("Ange ett namn: ")
namn5 = input("Ange ett namn: ")
print(namn5, namn4, namn3, namn2, namn1)

Programmeraren har bestämt att 5 och endast 5 namn ska matas in. Programmet fungerar varken för färre eller fler antal namn.

Det vore bättre om programmet ställer en fråga om hur många namn som ska matas in i början av programmet och användarens svar på denna fråga avgör om hur många variabler som ska användas till att lagra alla namn. Men programmeraren kan fortfarande inte veta hur många variabler som ska användas eftersom att olika användare kommer att kunna mata in olika antal namn. Hur ska programmeraren göra?

Lösningen är att använda en lista.

Vad är en lista?

En lista är variabel som kan ha flera värden. Varje värde får ett eget index (nummer) som kan användas för åtkomst eller modifiering av värdet. Om en vanlig variabel fungerar som en stol så fungerar en lista som en bänkrad i en biograf när det är numrerad placering. Telefonnummerlistan i din mobil är ett exempel på en lista.

Hur använder man en lista?

Listor skrivs med hjälp av klamrar []

lista = []
djurlista = ["katt", "hund", "ko"]

namnlista = 3*[None]

Bild:800156.jpg

namnlista blir då en variabel som har plats för 3 olika värden. None betyder att alla platserna ska vara lediga. Om man vill tilldela första platsen i variabeln ett värde t ex talet 47 gör man på följande sätt:

namnlista[0] = 47

Bild:800157.jpg

I ovanstående rad är namnlista namnet på listan. [0] specificerar avsedd plats i listan, 0 är ett index som används för specificera första plats. =47 som vi vet sedan tidigare är en tilldelningssats. Hela raden gör att första plats i listan får värdet 47. Programmerare är lite lustiga på det sättet att 0 betyder första plats i en lista. Detta gäller i flera programspråk, t ex Java och C++.

Om man vill tilldela andra plats i listan ett nytt värde t ex "hej" använder man därför indexet 1:

namnlista[1] = "hej"

Bild:800158.jpg

För att skriva alla värden som finns i listan kan man skriva som nedan:

print(namnlista)

Om man endast vill skriva ut värdet på en specifik plats i vektorn får man använda sig av klamrar igen:

print(namnlista[2])

Raden ovan skriver ut värdet som finns på tredje platsen i listan.

Åter till exemplet

Nu när vi har lärt oss lite om listor ska vi försöka skriva programmet som frågar efter ett antal namn och skriver ut dem i omvänd ordning:

 1. antal_namn=int(input("Hur många namn vill du mata in? "))
 2. namnlista = antal_namn*[None]
 3. i = 0
 4. while i < antal_namn:
 5.     namnlista[i] = input("Ange ett namn: ")
 6.     i += 1
 7. j = antal_namn - 1
 8. while j>= 0: 
 9.     print(namnlista[j])
10.     j -= 1

I rad nr 1 frågar programmet efter ett tal (antal namn). Inmatningen lagras i variabeln antal_namn. Funktionen int omvandlar den inmatade teckensträngen till ett heltalsvärde.

I rad 2 skapar vi en lista som har lika många platser som användarens svar från första raden.

I rad 3 använder vi iterationsvariabeln "i" som ska användas i while-slingan som finns i rad 4-6.

Rad 4 - 6 är en while-slinga som ska upprepa satsen i rad 5 så länge variabeln i är mindre än antalen namn som ska matas in.

Rad 5 frågar användaren efter ett namn och svaret kommer att lagras på i:te platsen i namnlista. I rad 6 vi ökar det värde som i har med 1.

En sammanfattning av den första while-slingan är att variabeln "i" startar med värdet 0 och i första varvet i slingan kommer att namnlista[i] alltså motsvara namnlista[0] eftersom i är 0. Alltså tilldelas första plats i listan ett nytt värde. Sedan när "i" ökas med 1 så får variabeln i värdet 1. Och i andra varvet kommer namnlista[i] motsvara namnlista[1] dvs andra plats i listan osv.

Detta upprepas tills i blir lika med antal_namn och alla platser i listan har fått ett värde.

När while-slingan i rad 4-6 är klar kommer listan innehålla så många namn som användaren ville mata in. Nu är det dags att programmet skriver ut alla namn i omvänd ordning. För att skriva ut sista namnet först måste vi ta reda på index för den sista namn som matades in.

Vi vet att index för första namnet är 0, index för andra namnet är 1 och index för tredje namnet är 2 osv. Men vad är index för det sista namnet?

Vi vet att antal namn som har matats in är lika många som värdet antal_namn (rad 1 i programmet). Om antal_namn t ex har värdet 10 så ska sista namnet ha placerats i plats nummer 9(=10-1).

I rad nummer 7 vill vi tilldela variabeln j ett startvärde, startvärdet ska vara samma värde som index för sista namnet i listan. Med ovanstående kunskap vet vi att j=antal_namn-1 kommer att vara index för den sista plats i listan.

Rad 8-10 är en while-sats som skriver alla element från namnlista i omvänd ordning.

Så här fungerar den andra while-satsen. Variabeln "j" har ett startvärde som är lika med index för sista platsen. While-satsen ska upprepa print-satsen(rad 9) så länge variabeln "j" har ett värde som är större eller lika med 0. Första varvet i slingan kommer att namnlista[j] motsvara sista namnet som finns i listan eftersom att "j" har just ett värde som är lika stort som index för sista namnet. På rad 10 kommer värdet av variabeln "j" minskas med 1. Alltså "j" kommer att ha samma värde som index för näst sista namnet i listan och därför i andra varvet i slingan kommer att namnlista[j] motsvar näst sista namn i listan osv.

Mer om listor

Det finns ytterligare några list-kommandon som är bra att känna till.


Uppslagslistor

Ibland så har man en mängd data där det inte är naturligt att numrera elementen som i en vanlig lista. Då kan man istället använda en uppslagslista (dictionary). En uppslagslista består av ett antal poster, där varje post har en nyckel och ett värde. I följande exempel så håller vi reda på antalet dagar per månad med hjälp av en uppslagslista. I varje post så finns det en nyckel, som är en textsträng som innehåller månadens namn, och ett värde, som är ett tal som anger antalet dagar i månaden. Man kan använda både strängar och tal som nycklar och värden.

month = {"jan":31, "feb":28, "mar":31, "apr":30, "maj":31, "jun":30,
         "jul":31, "aug":31, "sep":30, "okt":31, "nov":30, "dec":31}

print(month["feb"])   # Skriver ut 28
month["feb"] = 29     # Ändrar "feb":s värde till 29
print(month["feb"])   # Skriver ut 29

# Tar bort en post och lägger till två nya i uppslagslistan.
del month["feb"]
month["feb_vanlig"] = 28
month["feb_skotte"] = 29

# Skriver ut False eftersom månaden "qui" inte finns med i uppslagslistan.
# (Quintilis döptes om till juli för att ära Julius Caesar.)
print ("qui" in month)

# Metoden keys() ger en lista med alla nycklar i uppslagslistan.
# Utskriften blir (observera att en uppslagslista inte är ordnad):
# ['mar', 'okt', 'aug', 'sep', 'apr', 'jun', 'feb_vanlig',
#  'jul', 'jan', 'feb_skotte', 'nov', 'maj', 'dec']
names = month.keys() 
print(list(names))


Slingor

Det är så pass vanligt att man går igenom listor eller strängar från början till slut att det finns ett särskilt kommando för detta i Python, den så kallade for-satsen. Utskriften från följande program

tanter = ["Brun", "Grön", "Gredelin"]
for tant in tanter:
    print("Tant", tant)

blir

Tant Brun
Tant Grön
Tant Gredelin

For-satsen har alltså följande format

for <index> in <lista>:
    <sats>

där <index> är ett variabelnamn, <lista> en lista och <sats> en sats som kommer att utföras en gång för varje element i listan. I det första varvet av listan så kommer variabeln <index> att innehålla det första elementet i listan, i det andra varvet så innehåller den det andra elementet, och så vidare.

For-kommandot kan också användas för att gå igenom de flesta ordnade typer, till exempel en sträng. Här är ett exempel där vi använder en for-sats för att kontrollera om tecknet W finns med i en sträng:

alfabetet ="ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ"
for bokstav in alfabetet:
    if bokstav == "W":
        print("Ja, W fanns med i alfabetet!")

For-satsen är också mycket användbar om man vill gå igenom en lista av tal, sådana listor kan man nämligen snabbt och lätt skapa med hjälp av kommandot range(). Här är ett exempel:

#Skriver ut: 1 2 3 4 5 6 7 8 9
for i in range(1, 10):
    print(i, end=" ")
print()

Man anger en range med hjälp av startvärde, slutvärde och uppräkning. Observera att startvärdet finns med i listan, slutvärdet är däremot en övre gräns som inte finns med i listan. Här är ett par exempel:

a = range(100)         # [0, 1, 2, 3,..., 99]
b = range(0, 100, 5)   # [0, 5, 10, 15,..., 95]


Moduler

Stora program delar man upp i mindre delar med bland annat funktioner. Funktionerna kan placeras i olika filer. En fil med en samling av funktioner kallas för modul. För att vi ska kunna använda en viss funktion från en viss modul måste vi importera tillhörande modul innan anropet av funktionen. Importeringen kan man göra med en enkel import-sats som vi förklarar nedan.

Man kan ha stort nytta av modularisering i program. Med modularisering kan man återanvända kod vilket gör att man inte behöver lägga tid på och anstränga sig för att skriva en motsvarande kod som redan har skrivits. Dessutom blir stora program med flera tusen rader kod mer överskådliga om de delas upp på ett bra sätt i moduler. I denna kurs tar vi inte upp hur man modulariserar utan vi nöjer oss med att lära hur man anropar funktioner som finns i moduler.

När man installerar Python medföljer en hel del moduler. För att använda en funktion som finns i en modul måste man importera modulen. Detta gör man med hjälp av reserverade orden from, import och modulnamnet. Information om vilka moduler som följer med och vilka funktioner finns i varje modul kan man hitta i standardbiblioteket.

Anta att vi behöver beräkna roten ur 23 i ett program. Vi har från avsnittet matematiska funktioner i standardbiblioteket fått informationen att i modulen math finns en funktion som heter sqrt(x) som beräknar roten ur x och returnerar svaret. För att använda funktionen ska man importera modulen genom att skriva följande sats:

from math import *

Först nu efter importeringen kan vi anropa funktionen sqrt enligt nedan:

sqrt(23)

Observera att import-satsen behöver endast vara med en enda gång för att man ska kunna anropa en funktion flera gånger i ett program. import-satser placeras i början av programmet.


Random

Ett exempel på en modul som man kan importera är random som förser programmeraren med slumptal. Ibland vill vi att ett program ska vara oförutsägbart. Dvs det ska inte gå att förutse vad som kommer att hända i nästa stund av programmet. Detta beteende är väldigt vanlig i t ex spel där spelet byter strategier eller beter sig olika vid olika tillfällen. T ex ett äventyrsspel där det plötsligt kan dyka upp ett monster. Detta kan man åstadkomma med hjälp av slumpfunktionen random() som finns i modulen random. En modul är en samling med funktioner och annat som kan vara till användning i många program och är ett sätt att organisera funktioner. Mera information om modulen random hittar du bland pythonlänkarna på kursens huvudsida.

För att kunna använda funktionen random() måste man ha importerat modulen random i programmet, detta gör man med den enkla import-satsen:

from random import *

Efter denna sats kan man anropa funktionen random() som genererar ett slumptal (decimal) från och med 0 till 1. Till exempel:

from random import *
s_tal = random()

s_tal kommer då att ha ett värde som är mindre än 1 och större eller lika med 0.

Om man vill generera heltal så kan man använda funktionen randrange() som också finns i modulen random.

h_tal=randrange(1,3)

Variabeln h_tal kommer att bli heltalet 1 eller heltalet 2. randrange(a,b) betyder att slumpa ett heltal, heltalet kommer att vara större eller lika med a och mindre än b.


Test 3

Dags för test nummer 3. Testet hittar du som vanligt under rubriken Examination på kursens förstasida. Även detta test rättas automatiskt och du har möjlighet att göra om testet flera gånger om du inte lyckas på första försöket.