onsdag 28 november 2012

Introduktion till listor

Om du behöver två tal för en beräkning kan du skapa två variabler, en för varje tal. Men hur gör du om du behöver 100 tal. Än värre om du inte vet i förväg exakt hur många tal som du vill använda?

Listor löser det problemet. En lista är ett objekt som kan innehålla många tal, strängar (texter) mm. till och med andra listor.

Listor och index

Ett sätt att se på listor är som en rad med lådor. Hela raden tillsammans bildar listan och varje låda kan fyllas med olika innehåll. För att kunna hitta rätt låda är de numrerade, indexerade, från 0 och uppåt. Varje låda kallas ett element i listan.  Bilden nedan visar hur man i Python skapar listan min_lista och samtidigt fyller den med 6 olika tal samt hur man kan tänka sig talen placerade i lådor efter varandra numrerade 0 till 5.  Notera att indexeringen börjar på 0!


För att läsa av ett element i listan anger man listans namn följt av indexet för elementet inom hakparenteser. Tex. print(min_lista[2]) skriver ut talet 30.

Vill man ha reda på hur många element som finns i listan kan man använda funktionen len(<listans namn>).  Tex. ger len(min_lista) svaret 6

Övning 2.5
Skriv följande program som skapar ovanstående lista samt skriver ut de ingående elementen.

min_lista=[70, 40, 30, 40, 20, 80]
for i in range(len(min_lista)) :
    print(min_lista[i])

Man kan notera att range(len(min_lista)) faktiskt skapar en ny (namnlös) lista [0, 1, 2, 3, 4, 5] som sedan används för att gå igenom indexen i min_lista.

Övning 2.6
Det går utmärkt att skriva ut en lista med print. Då skrivs den ut med hakparenteser och kommatecken. Byt ut for-loopen i övning 2.5 mot print(min_lista) och testa.


Praktiska list-metoder

Förutom len-funktionen så finns det flera metoder som är unika just för listor som hjälper programmeraren. Dessa skrivs som listans namn, punkt, metoden. Till exempel min_lista.append(90) som lägger till ett nytt element sist i listan med värdet 90. 

Tabellen nedan visar standardfunktionerna:
Metod Beskrivning
append(x) Lägger till ett nytt element sist i listan och fyller det med x
count(x) Räknar hur många element i listan som är lika med x
extend(li) Sätter i hop två listor till en. Listan li läggs till efter den ursprungliga listan.
index(x) Letar upp det första elementet som är lika med x och returnerar indexet för detta element.
insert(i, x) Stoppar in x som ett nytt element på platsen i. Det element som förut hade index i flyttas upp till i+1 och hela listans längd ökar med 1.
pop() Returnerar det sista elementet i listan och tar bort det. Listans längd minskar med 1
remove(x) Raderar det första elementet som är lika med x. Listans längd krymper med 1.
reverse() Vänder ordningen på elementen i listan.
sort() Sorterar listan i storleksordning från minsta till största elementet


Radera element
Som synes ovan saknas en viktig metod. Nämligen att kunna ta bort ett eller flera element mitt i lista om man vet indexet. Detta görs istället med kommandot del:

 del li[i:j]

Ovanstående tar bort alla element från och med index i till (inte till och med!) j ur listan li och krymper den med motsvarande längd.

Notera: Kommandot del kan även användas för att radera variabler, hela listor och mycket annat

Fylla en lista med ett värde
Det är vanligt att man vill fylla en lista med ett och samma initialvärde, ofta noll. Detta kan i Python göras med *-tecken som för strängar. Följande fyller listan li med n st nollor:

li = [0] * n

Övning 2.7
Skriv och kör följande program som testar de olika metoderna samt kommandot del.

min_lista=[70, 40, 30, 40, 20, 80]
print(min_lista)

print("append 90")
min_lista.append(90)
print(min_lista)

print("count för 40")
print(min_lista.count(40))

print("extend med listan [60, 50, 90]")
li=[60, 50, 90]
min_lista.extend(li)
print(min_lista)

print("index för 90")
print(min_lista.index(90))

print("insert 10 på index 1")
min_lista.insert(1,10)
print(min_lista)

print("pop")
print(min_lista.pop())
print(min_lista)

print("remove 60")
min_lista.remove(60)
print(min_lista)

print("reverse")
min_lista.reverse()
print(min_lista)

print("sort")
min_lista.sort()
print(min_lista)

print("Raderar från och med index 3 till index 6")
del min_lista[3:6]
print(min_lista)

Övning 2.8
Skriv och testa följande program som fyller på en lista med tal som användaren matar in.

a=[] #Skapar en tom lista

#Fyller på listan
while True :
    try :
        s=input("Ange ett tal (N för att sluta):")
        e = float(s)
        a.append(e)
    except ValueError :
        if s == "N" : break
        else : print("Fel. Försök igen")

print(a)

Uppgift 2.3
Använd övning 2.8 samt listmetoder för att skriva ett program som talar om medianen av de inskrivna talen.

onsdag 21 november 2012

Moduler


Moduler

För att kunna återanvända funktioner  i olika program kan man samla dem i filer. I Python heter filer med funktionssamlingar moduler. (Även filer med hela program kallas moduler). Vi har tidigare använt modulen math som innehåller många matematiska funktioner samt modulen random som har slumptalsfunktioner.

Modulens namn är samma som filnamnet men utan filnamnstillägget (.py).

När du importerar en modul importeras funktionerna till programmet och kan användas genom  minmodul.minfunktion(). Ex:

#importerar modulen
import minmodul

#Kör en funktion i den importerade modulen
minmodul.minfunktion()

OBS! Om du importerar en modul kommer eventuell programkod utanför funktioner att köras direkt. Se nedan.

Övning 2.4 2.4b
Du ska nu skapa en modul med funktioner för matematik kring division och primtal. Använd nedanstående pseudokod för att skapa funktionerna. Namnge modulen som diskret_matematik

Funktionen primtal(n)
Kontrollerar om ett heltal tal n är ett primtal:

def primtal(n) :
    beräkna roten ur n (högsta möjliga talet som kan vara ett primtal)
    Sätt variabeln primtal till sant

    för alla heltal från och med 2 till och med roten ur n:
        om n är jämnt delbart med talet:
            sätt primtal lika med falskt
            hoppa ur loopen
        
    returnera värdet på primtal

Funktionen sgd(a, b)
Hittar största gemensamma delare hos för två heltal tal a och b:

def sgd(a, b) :
    om a större än b sätt variabeln storst till a och minst till b 
    annars sätt minst till a och storst till b
    
    om storst och minst är delbara returnera minst
    
    bestäm roten ur minsta talet plus 1
    
    för alla tal i från hetalsdelen av minst/2 till och med 1 :
        om både storst och minst går att dela med i :
            hoppa ur loopen
        
    returnera i

Funktionen mgn(a, b)
Hittar minsta gemensamma nämnare för två nämnare a och b:

    
def mgn(a, b) :
    returnera a multiplicerat med b delat med resultatet av sgd(a, b)


Funktionen main()

Ibland vill man ha programkod i en modul som ska importeras i andra program. För att förhindra att koden körs vid import används följande kod:

def minfunktion1()
    ...

def minfunktion2()
    ....

....

def main()
    # Kod som ska köras när modulen körs utan import

if __name__ == "__main__":
    main()

Variablen __name__ är en inbyggd variabel i Python som innehåller namnet på modulen om den importerats av ett program men "__main__" om modulen körs direkt.

Koden gör alltså att det du skrivit i funktionen main() endast körs om koden inte importeras.

Notera att namnet main() inte är något speciellt. Du kan skriva vilket funktionsnamn du önskar men main() har blivit en de facto standard.

Inlämningsuppgift 2.2
Lägg till en main()-funktion med tillhörande if-sats. Skriv kod som testar modulens funktioner.

måndag 19 november 2012

Speciella tal

Nedan följer några speciella tal som kan vara bra att känna till

Största heltalet
Det största heltalet som kan användas som index i till exempel strängar kan du finna med satsen sys.maxsize:

import sys

print(sys.maxsize)

Största flyttalet
Största decimaltalet som datorn klarar av ges av sys.float_info.max

import sys

print(sys.float_info.max)

Oändligheten och Not a Number
Inom matematiken finns det ibland  behov av att använda plus eller minus oändligheten. De skrivs:

float("Infinity")
float("-Infinity")

Funktionen math.isinf(x) returnerar sant om talet x är antingen positiva eller negativa oändligheten. (Du måste importera math-modulen för denna funktion.)
 
Ett annat speciellt "tal" är NaN, Not a Number, som är användbart när funktioner skall returnera ett flyttalsvärde men ett sådant inte går att räkna ut. Exempelvis grund av negativt tal under roten eller division med noll.

import math
x = float(input("Skriv ett tal"))
if x <o :
    x = float("nan")
else :
    x = math.sqrt(x)
print(x)

Det går att prova om talet är NaN med funktionen math.isnan(x) som returnerar sant om x är ett NaN.


Övning 2.4
Skriv om inlämningsuppgift 1.2 så att kontrollen av om det finns rötter och själva rotberäkningen sker i en funktion som returnerar NaN om talet under roten är negativt annars den beräknade roten. Se nedanstående pseudokod:

def roten(p, q) :
    t = talet under roten
    om t är negativt
        return NAN
    annars
        retur roten ur t

input p och q
r = roten(p,q)
om r NaN svara med att den saknar rötter
annars beräkna de två rötterna

Inlämningsuppgift 2.1
Skriv ett program som låter användaren mata in ett valfritt antal tal. Inmatningen avslutas med att användaren skriver ”N”. När alla talen är inmatade skriver programmet ut det största och det minsta av talen.

onsdag 14 november 2012

Funktioner

Del 2

Funktioner

Funktioner i programmering är en generalisering av funktionsbegreppet från matematiken. Se nedanstående bild där en matematisk definition av f(x) jämförs med motsvarande i Python:
Funktionerna har namnet f, de beror på variabeln x som kallas funktionens argument, och uttrycket definierar funktionen.

För Python gäller
  • Nyckelordet def inleder en funktionsdefinition
  • funktionens namn följs av en parentes med en kommaseparerad lista på argument. En funktion kan ha inga eller flera argument. Satsen avslutas med :
  • Ett block satser utgör koden i funktionen.
  • Satsen return följs av det värde eller objekt som skall returneras av funktionen. Satsen return är ej nödvändig. Om den saknas returnerar funktionen inget.
  • Funktionen avslutas när den når en return-sats eller när sista satsen i det indragna blocket exekverats.

Exempel på funktioner

Bilden ovan visar hur en funktion du känner igen från matematiken definieras i Python. Här följer några andra varianter av funktioner.

Största talet
Returnerar det tal som är störst av två tal a och b.

def storst(a, b) :
    if a > b : return a
    else : return b

Denna funktion har två argument och returnerar ett tal..

Slumpar en tipsrad
Returnerar en sträng "1", "X" eller "2". Obs! funktionen kräver en sats import random i början av filen för att fungera.

def tipsrad() :
    t = random.randint(1,3)
    if t == 1 : return "1  "
    elif t == 2 : return " X "
    else : return "  2"

Denna funktion har inget argument men returnerar en sträng.

Instruktionstext
Skriver ut instruktion till användaren.

def instruktion() :
    print("Välkommen till Månlanda!")
    print("Ditt mål är att landa mjukt.")
    print("Du har begränsad mängd bränsle. Lycka till!")

Denna funktion har varken argument eller returnerar ett värde. Dock är dessa typer av funktioner användbara för att förpacka kod. Antingen för att den ska upprepas på olika ställen i programmet eller för att göra programmet tydligare att läsa.

Rövarspråket
Gör om en text till rövarspråket.

def rovarsprak(text) :
   rt=""
   for c in text.lower() :
       if c in "bcdfghjklmnpqrstvwxz" :
           rt=rt+c+"o"+c
       else :
           rt=rt+c
 return rt

Denna funktion har en sträng som argument och returnerar en annan sträng som byggs upp från argumentet. Funktionen initierar en variabel, rt,  inom funktionen. Se mer om detta nedan.

Att använda funktioner

Före en funktion kan användas måste den vara definierad. Om funktionen i sin tur använder importerade funktioner måste importeringen göras före funktionsdefinitionen. Alltså placeras definitionerna före den kod som refererar till funktionen och efter eventuella importer. En god programstruktur är denna:
  1. importer
  2. globala variabler och konstanter (se nedan)
  3. funktionsdefinitioner
  4. huvudprogrammet
För att anropa en funktion  används funktionens namn följt av de argument man behöver skicka med.

Exempel på program som använder tipsradsfunktionen:

import random

def tipsrad() :
    t = random.randint(1,3)
    if t == 1 : return "1  "
    elif t == 2 : return " X "
    else : return "  2"

print("Tipsrad")
for i in range(13) :
    print(tipsrad())
print("====")

Övning 2.1
Skriv ett program som testar alla funktioner i ovanstående exempel.

Uppgift 2.1
Skriv en funktion som omvandlar temperatur i Fahrenheit till Celsius.

Variablers synlighet och överföring av argument

Variabler har olika synlighet (eng. scope). Det vill säga om de är nåbara från olika delar i programmet. I Python fungerar synligheten för variabler ungefär som tonade rutor i en bil. Variabler i huvudprogrammet är synliga inne i funktionen medan variabler i funktionen inte syns utanför.
  • Variabeln a kallas en global variabel och nås även inne i funktionen för avläsning av värdet ej ändring.
  • Funktionens namn f är synlig både i funktionen och utanför.
  • Argumentet x är en lokal variabel i funktionen och nås inte utifrån
  • Variabeln b initieras i funktionen och är endast nåbar inom funktionen
Om en variabel i en funktion har samma namn som en global så används den lokala variabeln.

Funktionsvariabler och argument raderas ur minnet när funktionen är avslutad. De globala variablerna "lever" under hela programkörningen.

De allra flesta språk har synlighetsregler liknande Python även om skillnader kan förekomma.

Variabler överförs till funktionsargument genom sitt värde. Alltså x i funktionen ovan får värdet 5 om den hade anropats med f(a). Eller med andra ord: när funktionen anropas skapas variabeln x och tilldelas värdet som lagras i a.

Notera: Objekt överförs via referens vilket gör att de hanteras annorlunda. Vi ser på det senare i kursen.

Övning 2.2
Skriv nedanstående program och testa.

a = 5
b = 2

def f(x) :
    a = x
    print("I funktionen a=" + str(a) + " x=" + str(x))

f(b)
print("Utanför funktionen a=" + str(a))

Notera:
Den globala variabeln a behåller sitt värde efter att funktionen returnerat.
Variabeln x får samma värde som b.

Övning 2.3

Varför fungerar inte nedanstående program?

a = 5

def f(x) :
    b = x + a
    print(b)

f(3)
print(b)


Undvik att använda globala variabler i funktioner
Det är lockande att använda globala variabler i funktioner men det bör undvikas om du inte har mycket goda skäl. Poängen med funktioner är att de ska vara återanvändningsbara i olika sammanhang. Om en funktion är beroende av variabler definierade utanför funktionen försvinner den möjligheten. Funktionen i uppgift 11 skulle ha skrivits och anropats enligt nedanstående exempel i ett riktigt program:

a=5
 
def f(x, y) :
    b = x + y
    print(b)

f(3,a) 


Uppgift 2.2
Skriv om programmet i repetitionsuppgift 1.8 så att själva testet om det är ett primtal görs i en funktion som returnerar sant eller falskt.

Överkurs
Python har en variant av anonym funktion (funktion utan namn) som kallas lambda.
Den återfinns även i språket Lisp. Du kan läsa om lambda här.

tisdag 6 november 2012

Mer repetitionsövningar på del 1

Rep 12
Slutför programmet så att du får en utskrift av "Hej på dej" utan att ändra i de givna raderna.

h = "Hej"
p = "på dej" 


Rep 13
Skriv ett program som finner det första stället då strängen "hus" förekommer i texten "Vissa hus har hjul, de är husvagnar"  

Rep 14
Skriv ett program som finner det andra stället då strängen "hus" förekommer i texten "Vissa hus har hjul, de är husvagnar"

Rep 15
Skriv ett program som räknar ner från 10 till noll.

Rep 16
Skriv en if-sats som är sann om x är större än 5 men mindre än 10.

Rep 17
Skriv en if-sats som är sann om x är mindre än 5 eller större än 10.

Rep 18
Skriv en if-sats som är sann om x är större eller lika med 5 men mindre än 10.

Rep 19
Sktiv en if-sats som är sann om x är större än 5 eller mindre än 0 men skild från 10.

Rep 20
Skriv ett program som beräknar fakulteten av ett inskrivet positivt heltal. (Fakulteten för N är 1*2*3*...*N.)