Mera strängar och listor
Du är redan bekant med syntaxen []
för att plocka ut/slica en delsträng:
strang = "exempel"
print(strang[3:7])
mpel
Samma syntax fungerar med listor. Dellistor kan extraheras på samma sätt som delsträngar:
lista = [3,4,2,4,6,1,2,4,2]
print(lista[3:7])
[4, 6, 1, 2]
Mera extrahering
Syntaxen []
fungerar faktiskt mycket lika som range
-funktionen, vilket innebär att vi också kan ge den steg-information:
strang = "exempel"
print(strang[0:7:2])
lista = [1,2,3,4,5,6,7,8]
print(lista[6:2:-1])
eepl [7, 6, 5, 4]
Om vi lämnar bort något av indexen kommer operatorn att inkludera alla element. Vi kan därför till exempel skriva ett mycket kort program som svänger på en sträng:
strang = input("Mata in en sträng: ")
print(strang[::-1])
Mata in en sträng: exempel lepmexe
Varning: globala variabler inne i funktioner
Vi har sett att det går att tilldela nya variabler inne i funktionsdefinitioner. Funktionen har också åtkomst till de variabler som finns utanför funktionen, i huvudfunktionen. Dessa variabler kallas globala variabler.
Att använda globala variabler inifrån funktioner är oftast en dålig idé. Det kan orsaka en hel del problem, till exempel buggar som är svåra att spåra.
Här är ett exempel på en funktion som använder en global variabel "av misstag":
def svangd_utskrift(namn: list):
# använder av misstag den globala variabeln namnlista
i = len(namnlista) - 1
while i >= 0:
print(namnlista[i])
i -= 1
# global variabel
namnlista = ["Antti", "Emilia", "Erkki", "Margaret"]
svangd_utskrift(namnlista)
print()
svangd_utskrift(["Louise", "Ophelia", "Lotta"])
Margaret Erkki Emilia Antti
Margaret Erkki Emilia Antti
Även om funktionen anropas korrekt skrivs alltid namnen i den globala variabeln namnlista
ut.
All kod som testar funktioner ska skrivas inom ett separat block så att TMC-testen accepterar koden. Föregående exempel ska alltså skrivas så här:
def svangd_utskrift(namn: list):
# använder av misstag den globala variabeln namnlista
i = len(namnlista) - 1
while i >= 0:
print(namnlista[i])
i -= 1
# kod som testar funktionen placeras här
if __name__ == "__main__":
# global variabel
namnlista = ["Antti", "Emilia", "Erkki", "Margaret"]
svangd_utskrift(namnlista)
print()
svangd_utskrift(["Louise", "Ophelia", "Lotta"])
Nu definieras också den globala variabeln i if-blocket.
TMC-testen körs alltid så att koden inom dessa if-block inte körs. Därför fungerar funktionen inte ens i teorin eftersom variabeln namnlista
inte finns då testen körs.
Strängar är oföränderliga
Strängar och listor har en hel del likheter, framför allt då det kommer till hur de fungerar med olika operatorer. En nyckelskillnad är att strängar är oföränderliga. Det betyder att de inte kan ändras.
strang = "exempel"
strang[0] = "a"
Vi kan inte byta ut tecken i en sträng, så det här programmet kommer att ge ett felmeddelande:
TypeError: 'str' object does not support item assignment
Ett liknande fel uppstår om du försöker sortera en sträng med sort
-metoden.
Strängar är oföränderliga, men variablerna som lagrar dem är inte det. En sträng kan ersättas med en annan sträng.
De följande exemplen är alltså till sin grund olika:
lista = [1,2,3]
lista[0] = 10
strang = "Hej"
strang = strang + "!"
Det första exemplet ändrar på innehållet i den lista som man hänvisar till. I det andra exemplet ersätts referensen till den ursprungliga strängen med en referens till en ny sträng. Den ursprungliga strängen finns fortfarande någonstans i datorns minne, men vi har inte längre någon variabel som är kopplad till strängen, och den kan därför inte längre användas i programmet.
Vi återkommer till det här senare, i samband med listreferenser.
Fler metoder för listor och strängar
Metoden count
räknar antalet gånger ett element eller en delsträng finns i en lista eller sträng:
strang = "Hon håsa på hussatimmen så lärar'n sa sakta: städa upp mjölet på golvet så att klassen int' e som en savann"
print(strang.count("sa"))
lista = [1,2,3,1,4,5,1,6]
print(lista.count(1))
5 3
Metoden räknar inte överlappande förekomster. Till exempel i strängen aaaa
räknar metoden upp till två förekomster av delsträngen aa
, även om det finns tre stycken om överlappande förekomster skulle tillåtas ("aa**" "aa". "**aa").
Metoden replace
skapar en ny sträng där en specifik delsträng har ersatts med en annan sträng:
strang = "Hej alla"
ny = strang.replace("Hej", "God eftermiddag")
print(ny)
God eftermiddag alla
Metoden påverkar alla delsträngar som hittas:
mening = "de åtta potatissemlorna förvandlades till en stor potatisplåt i ugnen – läraren, ja hon suckade i sitt hörn av klassen"
print(mening.replace("en", "EN"))
de åtta potatissemlorna förvandlades till EN stor potatisplåt i ugnEN – lärarEN, ja hon suckade i sitt hörn av klassEN
När replace
-metoden används, är ett vanligt misstag att man glömmer att strängar är oföränderliga:
strang = "Jag gillar Python"
# vi ersätter en delsträng, men resultatet lagras ingenstans
strang.replace("Python", "Java")
print(strang)
Jag gillar Python
Om den gamla strängen inte längre behövs kan man tilldela den nya strängen till samma variabel:
strang = "Jag gillar Python"
# vi ersätter en delsträng och lagrar resultatet
strang = strang.replace("Python", "Java")
print(strang)
Jag gillar Java
Skapa ett större programmeringsprojekt
Den här fjärde modulen avslutas med ett lite större programmeringsprojekt där du får utnyttja det du lärt dig hittills.
Den viktigaste regeln när man börjar med ett programmeringsprojekt är att man inte ska försöka lösa alla problem samtidigt. Programmet ska bestå av mindre delar, till exempel hjälpfunktioner. Du ska testa att varje del fungerar innan du går vidare. Om du försöker göra för mycket samtidigt kommer du högst antagligen hamna i en situation som präglas av kaos och mera kaos.
Du kommer att behöva ett sätt att testa dina funktioner utanför huvudfunktionen. Du kan göra det genom att definiera en skild huvudfunktion som du anropar utanför alla andra funktioner i programmet. Det är enkelt att tillfälligt kommentera bort ett funktionsanrop när man testar programmet. De första stegen i ditt programmeringsprojektet skulle kunna se ut så här:
def main():
poang = []
# programkod
main()
Nu kan hjälpfunktionerna köras utan att huvudfunktionen körs:
# hjälpfunktion som beräknar vitsord baserat på givet poängantal
def vitsord(poang):
# funktionens kod
def main():
poang = []
# programmets kod
# kommenterar bort huvudprogrammet
#main()
# testar hjälpfunktionen
poang = 35
resultat = vitsord(poang)
print(resultat)
Skicka data från en funktion till en annan
När ett program innehåller flera funktioner uppstår frågan: hur skickar jag data från en funktion till en annan?
I följande exempel ber programmet användare mata in några heltal. Programmet skriver sedan ut dessa värden och utför en "analys" på dem. Programmet är uppdelat i tre skilda funktioner:
def las_fran_anvandare(antal: int):
print(f"Ange {antal} tal:")
tal = []
for i in range(antal):
t = int(input("Ange tal: "))
tal.append(t)
return tal
def skriv_ut(tal: list):
print("Talen är: ")
for t in tal:
print(t)
def analysera(tal: list):
medeltal = sum(tal) / len(tal)
return f"Antalet tal {len(tal)}, medeltal {medeltal}, minsta {min(tal)} och största {max(tal)}"
# "huvudprogram" som använder funktionerna
indata = las_fran_anvandare(5)
skriv_ut(indata)
analysens_resultat = analysera(indata)
print(analysens_resultat)
När programmet körs, skulle det kunna se ut så här:
Ange 5 tal: Ange tal: 10 Ange tal: 34 Ange tal: -32 Ange tal: 99 Ange tal: -53 Talen är: 10 34 -32 99 -53 Antalet tal 5, medeltal 11.6, minsta -53 och största 99
Idén är att huvudfunktionen "lagrar" all data som behandlas av programmet. I det här fallet är det enda vi behöver de värden som användaren matat in, i variabeln tal
.
Om dessa värden behövs i en funktion skickar vi den motsvarande listvariabeln som ett argument. Det här sker i funktionerna skriv_ut_resultat
och analysera
. Om funktionen resulterar i data som behövs på annat håll i programmet, returnerar funktionen det. Det här sparas i en variabel i huvudfunktionen. Det här sker med funktionerna indata_fran_anvandare
och analysera
.
Du kunde också använda den globala variabeln tal
från huvudfunktionen direkt i hjälpfunktionerna, men vi har redan gått igenom varför det är en dålig idé. Här följer ännu en annan förklaring: om funktionerna kan ändra på den globala variabeln kan oförutsedda saker börja hända i programmet, framför allt då antalet funktioner ökar.
Att skicka data ut och in från funktioner gör man alltså helst med hjälp av argument och returvärden.
Du kunde också göra huvudfunktionen till en egen funktion. Då skulle variabeln tal inte längre vara en global variabel, utan en lokal variabel i main
-funktionen:
# funktion som representerar huvudfunktionen
def main():
indata = las_fran_anvandare(5)
skriv_ut(indata)
analysens_resultat = analysera(indata)
print(analysens_resultat)
# start av programmet
main()
Log in to view the quiz
Vänligen svara på en kort enkät om den här veckans material.
Log in to view the quiz
Se dina poäng genom att klicka på cirkeln nere till höger av sidan.