tisdag 21 maj 2013

Exempel på rekursion

Tre exempel på rekursiva funktioner


def fakultet(n):
    if n == 0 : return 1
    else : 
        return n*fakultet(n-1)
 
def artitmetisk_summa(n, d):
    if n == 0 : return 0
    else : return n*d+artitmetisk_summa(n-1, d)
    
   
def binar_sokning(a, l, min, max):
    if l[max] == a : i=max
    else :
        mitt = (min+max) // 2
        if a > l[mitt] : i=binar_sokning(a,l, mitt, max)
        else : i=binar_sokning(a,l, min, mitt)
    return i

print("Fakultet " + str(fakultet(5)))
print("Summa " + str(artitmetisk_summa(4, 2)))
lista=[1, 3, 5, 8, 9, 10, 12, 16]
print("Sökning " + str(binar_sokning(16, lista, 0, 7)))


En rekursiv funktion kallar på sig själv tills ett begränsande villkor är uppfyllt. Fakultetsberäkningen ovan kan beskrivas med denna bild:


Först byggs stacken av funktionsanrop upp tills fakultet(0) returnerar 1. När detta sker vänder det och stacken krymper då varje steg returnerar sina värden. Slutligen returnerar fakultet(5) sitt värde till print som skriver ut det.

Uppgift 3.3
Skriv och testa en rekursiv funktion för att beräkna en geometrisk summa. (Du kan använda ** för upphöjt i Python.)


måndag 15 april 2013

Rörelse och interaktion

Automatisk rörelse

Tkinter har metoden after( tid, funktion) som anropar en funktion efter tiden tid som anges i millisekunder. Denna kan användas för att skapa rörelse i ett grafisk program.

Övning 3.9
Skriv in och testa programmet nedan:

from tkinter import *


class Dot_Canvas(Canvas):
    
    def __init__(self, root):
        super().__init__(root, width=400, height=300, bg="white")
        self.running=False
        self.bind("<Button-1>", self.start_stop)
        self.x=30
        self.y=30
        self.dx=5
        self.dy=5
        self.photo = PhotoImage(file="../greendot.gif")
        self.dot_id=self.create_image(self.x, self.y, image=self.photo)
        self.pack()
    
    def start_stop(self, event):
        if not self.running :
            self.running=True
            self.move_dot()
        else :
            self.running=False
        
    def move_dot(self):
        self.move(self.dot_id, self.dx, self.dy)
        self.x=self.x+self.dx
        self.y=self.y+self.dy
        if self.x < 10 or self.x > 390 : 
            self.dx=-self.dx
        if self.y < 10 or self.y > 290 : 
            self.dy=-self.dy
        if self.running :
            self.after(50, self.move_dot)

root = Tk()
root.title('Moving dot')
Dot_Canvas(root)
mainloop()

Notera funktionen hos programmet. När användaren klickar på musen sätts variabeln running till sant och metoden move_dot kallas på. Sist i metoden move_dot finns raden self.after(50, self.move_dot) denna kallar på move_dot efter 1/20 sekund. Alltså kommer move_dot att köras varje 1/20 sekund. En funktion eller metod som kallar på sig själv kallas rekursiv. När användaren klickar på musen igen blir running falskt och metoden move_dot slutar att kalla på sig själv.

 En mask

Genom att skapa en lista av gröna punkter och deras positioner man göra en studsande mask:

Övning 3.10
Skriv och testa:

from tkinter import *


class Dot_Canvas(Canvas):
    
    def __init__(self, root):
        super().__init__(root, width=400, height=300, bg="white")
        self.running=False
        self.bind("<Button-1>", self.start_stop)
        self.x=[10,20,30,40,50]
        self.y=[10,20,30,40,50]
        self.dx=[5,5,5,5,5]
        self.dy=[5,5,5,5,5]
        self.photo = PhotoImage(file="../greendot.gif")
        self.dot_id=[]
        for i in range(len(self.x)) :
            self.dot_id.append(self.create_image(self.x[i], self.y[i], image=self.photo))
        self.pack()
    
    def start_stop(self, event):
        if not self.running :
            self.running=True
            self.move_dot()
        else :
            self.running=False
        
    def move_dot(self):
        for i in range(len(self.dot_id)) :
            self.move(self.dot_id[i], self.dx[i], self.dy[i])
            self.x[i]=self.x[i]+self.dx[i]
            self.y[i]=self.y[i]+self.dy[i]
            if self.x[i] < 10 or self.x[i] > 390 : 
                self.dx[i]=-self.dx[i]
            if self.y[i] < 10 or self.y[i] > 290 : 
                self.dy[i]=-self.dy[i]
        if self.running :
            self.after(50, self.move_dot)

root = Tk()
root.title('Mask')
Dot_Canvas(root)
mainloop()


 Dra saker med musen

Genom att skilja på händelserna när man trycker ner och drar med musknappen nedtryckt kan man dra saker över en Canvas med musen. Programmet nedan använder också metoden find_closest för att välja den närmaste av de två punkterna.

Övning 3.11
Skriv och testa:

from tkinter import *


class Dot_Canvas(Canvas):
    
    def __init__(self, root):
        super().__init__(root, width=200, height=200, bg="white")
        self.dra_id=None
        self.dra_x=0
        self.dra_y=0
        self.bind("<ButtonPress-1>", self.ned)
        self.bind("<B1-Motion>", self.dra)
        self.photo = PhotoImage(file="../greendot.gif")
        self.create_image(40, 40, image=self.photo)
        self.create_image(160, 160, image=self.photo)
        self.pack()
    
    def ned(self, event):
        self.dra_id = self.find_closest(event.x, event.y)    
        self.dra_x=event.x
        self.dra_y=event.y
        
    def dra(self, event):
        dx=event.x-self.dra_x
        dy=event.y-self.dra_y
        self.move(self.dra_id, dx, dy)
        self.dra_x=event.x
        self.dra_y=event.y

root = Tk()
root.title('Dot')
Dot_Canvas(root)
mainloop()

Inlämningsuppgift 3.2
Skriv något av följande program och lämna in:

1) En analog klocka. Använd create_line och coords för att få visarna att vridas. Kan kompletteras med möjlighet att ställa klockan med musen.

2) Femtonspel - användaren klickar på den siffra hen vill flytta. Programmet utför flytten om det är möjligt och upptäcker om siffrorna är i rad.

3) Masken - Användaren styr en mask med knapp för sväng 90 grader höger eller vänster. Masken blir längre och längre. Man får inte krocka med väggar eller sig själv. Hinder kan införas och mm.

onsdag 27 mars 2013

En målarduk

För att visa olika former av grafik finns objektet Canvas.  Canvas använder ett koordinatsystem med origo i övre vänstra hörnet och en pixel per enhet. Y-axeln är riktad nedåt.

Exempel:

from tkinter import *

root = Tk()

w = Canvas(root, width=200, height=100, bg="white")
w.pack()

w.create_line(0, 0, 200, 100)
w.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))

w.create_rectangle(50, 25, 150, 75, fill="blue")

mainloop()

Metoder för att skapa objekt på en Canvas är:
  • create_line
  • create_rectangle
  • create_arc
  • create_oval
  • create_polygon
  • create_text
  • create_window
  • create_bitmap
  • create_image
Se sida 209-210 i boken samt här.

Som synes ovan kan du även konfigurera utseendet på olika objekt med hjälp av angivelser av färger (bg i koden ovan står för background colour) och andra attribut.

Uppgift 3.2
Rita en smiley med tkinters Canvas

Saker som rör sig och att reagera på musklick

Genom att binda en  händelsehanterare till en Canvas kan du göra olika saker vid musklick eller annat som användaren gör. Bindandet gör med metoden .bind("Namn", funktion).
Namn anger händelsen som ska bindas till funktionen. Se här för lista. Se även boken sid. 238-245
funktion är den funktion som ska köras vid händelsen. Alla händelsefunktioner har argumentet event som är en referens till händelseobjektet som innehåller data om händelsen.

Objekten som ritas på en Canvas kan modifieras och förflyttas efter att de ritats. Detta är möjlig då varje objekt ges ett unikt id-nummer i och med att det skapas. Vid förändringarna hänvisas till dessa id-nummer. Se även boken sid. 213-220

Nedanstående exempel ritar ut en bild med en grön prick. Om användaren klickar på musknappen flyttas pricken 10 pixlar snett nedåt.


from tkinter import *

root = Tk()
root.title('Dot')

def klick_b1(event):
    w.move(dot_id, 10, 10)

w = Canvas(root, width=200, height=200, bg="white")
w.bind("<Button-1>", klick_b1)
photo = PhotoImage(file="../greendot.gif")
dot_id=w.create_image(30, 30, image=photo)
w.pack()
mainloop()

Övning 3.7
Skriv in programmet ovan och testa. Bilden på den gröna pricken laddar du ner och placerar i din projektmapp:

  

Global eller klass

Funktioner kan normalt endast läsa globala variabler, inte ändra dem. Detta är ett problem för händelsebindningar i Python. Du skulle behöva skicka med informationen till funktionen som körs vid händelsen men tyvärr går inte det på ett enkelt sätt då man endast anger funktionens namn. Det finns två olika lösningar på problemet:

global

För att kunna ändra globala variabler i en funktion måste de deklareras först i funktionen med nyckelordet global. Ex:

from tkinter import *

root = Tk()
root.title('Dot')
x=30
y=30
dx=10
dy=10

def klick_b1(event):
    global x, y
    w.move(dot_id, dx, dy)
    x=x+dx
    y=y+dy
    print(str(x)+","+str(y))

w = Canvas(root, width=200, height=200, bg="white")
w.bind("<Button-1>", klick_b1)
photo = PhotoImage(file="../greendot.gif")
dot_id=w.create_image(x, y, image=photo)
w.pack()
mainloop()

Klass
Att använda global passar bra i mindre program men det är bättre att hantera objekt när programmen blir lite större. Genom att skapa en egen underklass till Canvas kan du lägga till de data och funktioner du behöver och hantera dessa. Denna lösning ger ser ut så här:

from tkinter import *


class Dot_Canvas(Canvas):
    
    def __init__(self, root):
        super().__init__(root, width=200, height=200, bg="white")
        self.bind("<Button-1>", self.klick_b1)
        self.x=30
        self.y=30
        self.dx=10
        self.dy=10
        self.photo = PhotoImage(file="../greendot.gif")
        self.dot_id=self.create_image(self.x, self.y, image=self.photo)
        self.pack()
        
    def klick_b1(self, event):
        self.move(self.dot_id, self.dx, self.dy)
        self.x=self.x+self.dx
        self.y=self.y+self.dy
        print(str(self.x)+","+str(self.y))

root = Tk()
root.title('Dot')
Dot_Canvas(root)
mainloop()

Lösningen med klass är som synes  "klumpigare" för små testprogram men har stora fördelar då programmen blir större. Den nya klassen Dot_Canvas innehåller allt den behöver för sin funktion och kan skapas enkelt i huvudprogrammet.

Använd valfri metod för att lösa nedanstående:

Övning 3.8
Ändra i programmet ovan så att punkten ser ut att studsa när den når sidorna på fönstret.


Uppgift 3.3
Händelseinformationen som finns i objektet event i koden ovan innehåller bland annat information om var muspekaren var när händelsen inträffade. Detta är lagrat som event.x och event.y. Använd exemplet ovan som grund till ett program som placerar den gröna pricken där användaren klickar.

onsdag 20 mars 2013

Textrutan Entry

Entry är en textruta för att skriva in enradstexter. Innehållet i textrutan sparas i en angiven variabel som är ett objekt av typen StringVar().  För att komma åt texten i textrutan används metoden get på textvariabeln. Se ex:

from tkinter import *

def ny_text(): 
    lbl.config(text=en1_text.get())
        
root=Tk()
root.title('Textruta')
root.minsize(200, 60)
en1_text = StringVar() #Variabeln som innehåller textrutans text
en1=Entry(root, textvariable=en1_text).pack(fill=X)
btn = Button(root, text ="Skriv", command = ny_text)
btn.pack(fill=X)
lbl = Label(root, text = "")
lbl.pack(fill=X)

root.mainloop()

För att ställa in texten i textrutan används metoden set("min text") på textvariabeln.

Övning 3.6
Ändra i programmet ovan så att knappen tömmer textrutan samtidigt som texten skrivs i etiketten.

Inlämningsuppgift 3.1
Använd ovanstående samt Övning 2.4 för att göra en grafisk version av ett program som löser andragradsekvationer och skriver ut svaret.

onsdag 13 mars 2013

Knappar som gör något

För att något ska hända när du trycker på en knapp anges vilket kommando (vanligen en funktion) som ska köras. Se exempel:

from tkinter import *

def sag_haj(): 
    lbl.config(text="Hej!")
        
root=Tk()
root.title('Count')
root.minsize(200, 100)
btn = Button(root, text ="Säg hej", command = sag_haj)
btn.pack(fill=X)
lbl = Label(root, text = "")
lbl.pack(fill=X)

root.mainloop()

Övning 3.4
Skriv in ovanstående program och testa,

Notera
I Python anges namnet på funktionen som skall köras. Den anropas inte. Där av endast namnet sag_haj utan () efter.

Global

För att kunna ändra globala variabler i en funktion måste du ange att du vill använda den globala variabeln mednyckelordet global anges före du utför ändringen. Detta är användbart när vi ska få knappar att göra saker om vi inte vill skapa objekt. Se nedan.

from tkinter import *

n=0

def oka_ett(): 
    global n
    n=n+1
    lbl.config(text=str(n))
        
root=Tk()
root.title('Count')
root.minsize(200, 100)
btn = Button(root, text ="+1", command = oka_ett)
btn.pack(fill=X)
lbl = Label(root, text = str(n))
lbl.pack(fill=X)

root.mainloop()


Genom att tala om att vi ska använda den globala variabeln n i funktionen oka_ett() kan vi utföra ändringen med kommandot från knappen.

Övning 3.5
Lägg till en knapp  i ovanstående program som minskar värdet på n med ett.

måndag 11 mars 2013

Placering i rutnät

Placering av etiketter och andra widgets i rutnät är en vanlig layoutmetod.

Nedanstående exempel skapar följande layout:



from tkinter import *

root = Tk()
root.title("tk")
root.minsize(200, 200)
#Skapar etiketter med ram
l1 = Label(root, text="Uppe Vänster", relief=RIDGE)
l2 = Label(root, text="Mitten Vänster", relief=RIDGE)
l3 = Label(root, text="Stor", relief=RIDGE)
l4 = Label(root, text="En längre text under", relief=RIDGE)
#Placerar in dem i rutnätet och anger att de ska fylla rutan
l1.grid(row=1, column=1, sticky=W+E+N+S)
l2.grid(row=2, column=1, sticky=W+E+N+S)
l3.grid(row=1, column=2,  columnspan=2, rowspan=2, sticky=W+E+N+S)
l4.grid(row=3, column=1, columnspan=3, sticky=W+E+N+S)

# Hur rader och columner ska uppföra sig vid ändring av fönsterstorleken
root.grid_columnconfigure(1, weight=1)
root.grid_columnconfigure(2, weight=1)
root.grid_columnconfigure(3, weight=1)
root.grid_rowconfigure(1, weight=1)
root.grid_rowconfigure(2, weight=1)
root.grid_rowconfigure(3, weight=1)

root.mainloop()

Se även boken sid. 165-166

Uppgift 3.1
Ändra i programmet ovan så att resultatet blir som i bilden nedan.

onsdag 6 mars 2013

Inroduktion till grafiskt gränssnitt

Vi använder det grafiska standardbiblioteket Tkinter. De objekt som det innehåller kallas widgets.

För att förenkla skapar vi en standardmodul som vi kan använda som mall när vi skapar våra objekt. Modulen sköter en del av det bakgrundsarbete som behövs.

Övning 3.1
En standardkod för att skapa grafiska objekt:

from tkinter import *

class myapp_tk(Tk):
    def __init__(self,parent):
        Tk.__init__(self,parent)
        self.parent = parent
        self.initialize()

    def initialize(self):
        pass #Här skrivs den kod som skapar de olika objekten i fönstret.

if __name__ == "__main__":
    app = myapp_tk(None)
    app.title('my application')
    app.mainloop()

Denna kos skapar ett widgetobjekt med namnet app och startar upp metoden mainloop(). Metoden mainloop är den loop som söter hantering av grafiken och reaktion på användarens inmatningar. Den är aktiv så länge objektet finns.

Att lägga till objekt i widgeten

Du lägger till objekt widgeten genom att först skapa ett nytt objekt som tillhör widgeten och sedan placera detta med metoden pack().

Övning 3.2
En etikett (label) med text. Byt ut innehållet i initialize(self) till:

    def initialize(self):
        self.label=Label(text="Hello World")
        self.label.pack()

Övning 3.3
Använd informationen i boken på sidan 158-163 för att testa pack-metoden och knappar.
 

tisdag 5 februari 2013

Moduler och arv

Klasser och moduler

Det går utmärkt att ha flera klasser i en modul. Om du då vill komma åt dessa klasser från en annan modul importerar du modulen. Som för funktioner skriver du sedan modulnamn.Klassnamn när du vill använda klassen. Ex:

import minmodul

...

# Skapar objektet mittobjekt av klassen MinKlass från modulen minmodul
mittobjekt = minmodul.MinKlass()

...

Övning 2.25
Kopiera klasserna för de geometrikska kropparna du skapat till en modul med namnet klossar (filnamnet är alltså klossar.py).

Arv eller klasser och underklasser

En av poängerna med objektorienterad programmering är arv av egenskaper mellan klasser. Vi kan skapa en huvudklass med de variabler och metoder som objekt i underklasser skall ha gemensamt.

Vi vill att alla klossar skall ha en position och en färg. Positionen skall vara en  lista med tre element [x, y, z] och färgen en textsträng. Vi vill kunna ändra färg och också ha möjlighet att flytta klossarna genom att ange en ny position.

Huvudklassen blir då:

#Huvudklass Klossar
class Kloss :
    def __init__(self):
        self.position =[0, 0, 0]
        self.farg=""
        
    def flytta(self,position):
        self.position=position
        
    def satt_farg(self, farg):
        self.farg=farg
  

Nu har vi grunden för metoder och variabler som kan ärvas av alla varianter av klossar vi skapar. Metoderna i underklasserna går före de i huvudklassen så då det finns en metod volym() i klassen Kub så körs den om objektet är en kub. Skulle det inte finnas en metod i underklassen så körs istället den i huvudklassen.Så om man kallar på metoden flytta för en kub så körs metoden i huvudklassen Klossar.

För att göra det lite snyggt  så inför vi tomma metoder i huvudklassen för de som ska implementeras i alla underklasser, alltså volym, area och skala. Genom detta är det lätt att se vad en underklass förväntas implementera. Tomma metoder skapas genom att lägga in pass som enda del i metodkroppen. Metoden skala(k) i huvudklassen Klossar ser alltså ut så här:

    def skala(self, k):
        pass

Övning 2.26
Lägg till tomma klasser för skala, volym och area i huvudklassen


Att skapa arvet

Nu måste vi få underklasserna att ärva metoder och variabler från huvudklassen.

För att tala om att en klass är en underklass till en annan anges huvudklassen i parentes bakom namnet på underklassen. I vårt fall ändrar vi i raden där vi definierar Kub till:

class Kub(Kloss) :

Nu är Kub en underklass till Klossar och har tillgång till dess metoder.För att Kub skall få samma variabler som huvudklassen ser vi till att huvudklassens initiering körs samtidigt som underklassens. Detta sker med hjälp av funktionen super(). super(). refererar till huvudklassen ungefär som self refererar till klassen själv.

Klassen Kub får med arv och initiering av variablerna i Klossar utseendet:

class Kub(Kloss) :
    
    def __init__(self, sida):
        super().__init__()
        self.sida=sida
        
    def skala(self, k):
        self.sida=self.sida*k
           
    def volym(self):
        return self.sida*self.sida*self.sida
    
    def area(self):
        return self.sida*self.sida*6

Övning 2.27
Skriv om övriga kloss-klasser så att de ärver metoder och variablerna från Klossar.

Övning 2.28
Skapa en ny modul, klosstest, och pröva att arvet fungerar:
Skriv och kör:

import klossar

kuben=klossar.Kub(8)
print(kuben.position)
kuben.flytta([1,2,3])
print(kuben.position)
kuben.skala(2)
print(kuben.volym())

Övning 2.29
Skriv tester för några av de andra kloss-typerna samt färgen också.

måndag 4 februari 2013

Övningar klasser

Vi ska skapa några klasser för att testa hur de fungerar. Vi skapar klossar av olika slag.
  • Kub
  • Rätblock
  • Pyramid - kvadratisk bas och symetrisk
  • Cylinder
  • Klot
En klass blir en ritning till var och en av klosstyperna. Vi vill förutom att skapa klossen även kunna få reda på dess volym och begränsningsarea.

Vi kan skapa alla klasserna i samma modul. Här är klassen för Kuben:

class Kub :
    
    def __init__(self, sida):
        self.sida=sida
        
    def volym(self):
        return self.sida*self.sida*self.sida
    
    def area(self):
        return self.sida*self.sida*6

Övning 2.22
Skapa klasser för de övriga klosstyperna i samma modul (fil). Tips: tänk på vilka mått som måste anges för de olika typerna och undvik åäö.

Vi kan nu använda klasserna för att skapa objekt och utföra beräkningar med dessa. Till exempel ta reda på sammanlagda volymen av en kub med sidan 8 och ett klot med radien 4. I huvudprogrammet skriver vi:

kuben=Kub(8)
klotet=Klot(4)
print(kuben.volym()+klotet.volym())

Uppgift 2.7
Bestäm sammanlagda arean av dessa tre objekt:
En pyramid med bas-sidan 5 och höjden 10
Ett rätblock med längden 8, bredden 4 och höjden 6
En cylinder med radien 5 och höjden 6

En metod som ändrar objektet

Ovanstående objekt kan inte förändras efter att de skapats. Vi kan göra de mer användbara genom att införa metoder som ändrar objektet. Till exempel ändrar dess storlek genom skalning. Följande version av klassen Ratblock kan skalas upp eller ned med metoden skala(k) där k är skalfaktorn:

class Ratblock :
    
    def __init__(self, langd, bredd, hojd):
        self.langd=langd
        self.bredd=bredd
        self.hojd=hojd
    
    def skala(self, k):
        self.langd=self.langd*k
        self.bredd=self.bredd*k
        self.hojd=self.hojd*k
    
    def volym(self):
        return self.langd*self.bredd*self.hojd
    
    def area(self):
        return self.langd*self.hojd*2+self.bredd*self.hojd*2+self.bredd*self.langd*2

Övning 2.23
Lägg till skalningsmetoder för övriga klasser.

Övning 2.24
Hur mycket ändrar sig begräsningsarea och volym på en kub med sidan 4 som skalas upp 10 ggr.

tisdag 29 januari 2013

Klasser och objekt

Klassen Complex

Nedanstående visar ett exempel på klass och objekt skapade ur klassen. Klassen Complex fungerar som ett paket för komplexa tal.

import math

#Klassens definition
class Complex:
     #Konstruktor
     def __init__(self, realdel, imagdel):
         self.r = realdel
         self.i = imagdel

     def abs(self):
         return math.sqrt(self.r*self.r+self.i*self.i)
        
#Använder klassen
#Skapar objekt z av klassen Complex
z = Complex(3.0, -4.5)
print(str(z.r) + ", " + str(z.i))
print(z.abs())

Nya objekt skapas med konstruktorn __init__(self, realdel, imagdel). Varje nytt komplext tal skapas med värden på realdel och imaginärdel. Klassen innehåller även en metod abs() som returnerar absolutvärdet av det komplexa talet.

Övning 2.18
Lägg till en metod som returnerar det komplexa talet som en textsträng som vi normalt skriver komplexa tal. Ex: 3+4i och 2-5i. Kalla metoden string(self)
Testa din metod.

Övning 2.19
Lägg till en metod arg() som returnerar argumentet för det komplexa talet.
Tips: math.atan2(y,x) returnerar vinkeln, i radianer, från x-axeln korrekt runt hela varvet.
Testa din metod.

Standardvärden

Du kan lägga till standardvärden till konstruktorn för att möjliggöra en standardversion av ditt objekt. Det görs genom att skriva som exemplet nedan:

def __init__(self, realdel = 0, imagdel = 0):

 Nu ger z = Complex() det komplexa talet 0+0i och z = Complex(5) talet 5+0i.
Du kan dock inte enbart ange imaginärdelen då standardvärdena ersätts från vänster till höger för varje angivet argument.

Använda referens till objekt i metod och anonyma objekt

Följande metod lägger till det komplexa talet z till det ursprungliga objektet

     def add(self, z):
          self.r=self.r+z.r
          self.i=self.i+z.i

Övning 2.20
Lägg till metoden ovan till klassen Complex och testa genom att i huvudprogrammet till exempel skriva:

z.add(Complex(5,1))
print(z.string())

Ovanstående skapar ett anonymt objekt av klassen Complex med värdet 5+i och lägger till det till det ursprungliga objektet.

Övning 2.21
Skapa motsvarande metoder som ovanstående för subtraktion, multiplikation och division. (Kom ihåg att vid division förlänger du med konjugatet till nämnaren.)


måndag 14 januari 2013

Sökning och sortering


Sortering

Att sortera listor och andra uppsättningar data är viktigt inom många användningsområden och det finns ett stort antal algoritmer för detta.

Läs om sorteringsalgoritmer här.

Python har  en inbyggd metod för att sortera listor som är mycket effektiv:
lista.sort()

Sökning i listor

Om listan är oordnad är det enklast att söka från början till slut tills man hittar det man söker. Man behöver då i snitt söka genom hälften av listan innan man finner det sökta värdet.

Är listan sorterad kan sökningen snabbas upp betydligt genom en smart metod.

Binär sökning
I en sorterad lista kan man veta om man är före eller efter det sökta värdet. Man gör därför så att man gissar på det mittersta värdet inom det område man inte uteslutit. Se nedanstående bild som visar sökning efter talet 76:


Efter första gissningen vet man att talet är i den övre halvan.
Efter den andra vet man att talet är i den tredje fjärdedelen.
osv tills man finner det.

Uppgift 2.6
Skriv ett program som:
  •  Låter användaren mata in ett valfritt antal tal (Avsluta inmatningen med tex. att användaren skriver N). Talen läggs i en lista.
  •  Sorterar listan av tal.
  •  Med hjälp av binär sökning letar fram ett tal som användaren matat in. (Förutsatt att det finns i listan. Annars ett meddelande om att det inte finns.)

tisdag 8 januari 2013

Stackar och köer

Stack

I en stack placeras nya data överst i stacken och data hämtas också överst i stacken. Ordningen kallas ibland LIFO ("Last In Frist Out"). Stackar används ofta i matematiska rutiner och är fundamental för den interna funktionen i datorer.


I köer placeras nya data längst bak i kön och data hämtas från början av kön. Ordningen kallas ibland FIFO ("First In First Out"). Köer används då det är viktigt att bevara ordningen på datan.

Exempel som buffer

Följande övningar visar exempel på hur stack och kö fungerar som buffrar. En buffer lagrar temporärt data. De kan bland annat användas för att kunna processa data i jämn takt trots att den inkommande datan kommer in i mer ojämn takt vid internetuppkopplingar, bränning av skivor och mycket mer. Nedanstående exempel visar principen för en sådan buffer i form av en stack och en kö.

Övning 2.16

#Simulerar en stack där 0-2 nya element tillkommer varje sekund och ett
# poppas.

import random
import time

#Fyller stacken med 6 bokstäver. A underst i stacken
stack = ["A", "B", "C", "D", "E", "F"]
alfa = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
i = 6
while True :
    try : 
        print("Processar " + stack.pop())    
        print(stack)
    except IndexError :
        print("Stacken tom! Avslutar")
        break
    
    antal_nya = random.randint(0,2)
    while antal_nya > 0 :
        stack.append(alfa[i])
        i = (i + 1) % 26
        antal_nya = antal_nya - 1
    time.sleep(1)
    
print("Slut")


Övning 2.17

#Simulerar en kö (buffer) där 0-2 nya element tillkommer varje sekund och ett
# poppas.

import random
import time

#Fyller kön med 6 bokstäver. A först i kön
queue = ["A", "B", "C", "D", "E", "F"]
alfa = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
i = 6
while True :
    try : 
        print("Processar " + queue.pop(0))    
        print(queue)
    except IndexError :
        print("Buffern tom! Avslutar")
        break
    
    antal_nya = random.randint(0,2)
    while antal_nya > 0 :
        queue.append(alfa[i])
        i = (i + 1) % 26
        antal_nya = antal_nya - 1

    time.sleep(1)
    
print("Slut")

tisdag 11 december 2012

Övningar med listor

Alla positiva heltal som inte själva är primtal går att dela upp i produkter av primtal. Detta kallas primtalsuppdelning. Ex: 28 = 2*2*7, 72 = 2*2*2*3*3, 39 = 3*13

Detta kan bland annat användas för att göra listor på primtal och för att göra snabbare funktion för att finna största gemensamma delare.

Övning 2.13
Lägg till en funktion till modulen diskret_matematik för  att skapa en funktion som utför primtalsuppdelning enligt nedanstående pseudokod:

def primtalsuppdelning(n):
    Skapa en tom lista kallad primtal
    sätt variabeln p till 2
    så länge som p är mindre eller lika med n:
        om n är jämnt delbart med p:
            lägg till p i listan primtal
            dividera n med p
        annars :
            öka p med ett
            
    returnera primtal

Övning 2.14
Använd primtalsuppdelningen ovan till att göra en betydligt effektivare version av funktionen sgd(a, b). Byt ut den befintliga mot denna version. Pseudokod:

def sgd(a, b):
    sätt storst till det största talet av a och b samt
    minst till det minsta
        
    om storst jämnt delbart med minst returnera minst
    primtalsuppdela minst och spara resultatet i listan prim
    antag att största gemensamma delare, sgd är 1
    för alla tal p i prim :
        om storst jämnt delbart med p :
            dela storst med p
            multiplicera sgd med p
            
    returnera sgd


Övning 2.15
Uppdatera main() i diskret_matematik med tester av primtalsuppdelningen och testkör.

Uppgift 2.5
Skriv ett program som hittar primtal genom att använda Eratosthenes såll.
Bild: Wikipedia

onsdag 5 december 2012

Mer om listor

Forsatsen och listor

Om du inte behöver veta indexet kan du använda dig av for-satsens förmåga att iterera över listor.

Övning 2.9

lista = ["Hej", "alla", "glada"]

for e in lista :
    print(e, end = " ")

 Listor är objekt

Listor är objekt i Python. Det skiljer dem från tal och strängar. Objekt är behållare för variabler och även i många fall metoder. Deras innehåll kan förändras utan att skapa ett nytt objekt.

Jämför hur du lade ihop två textsträngar med:

s = s + t

du inte kan förändra strängen s utan måste skapa en ny sträng som sedan ersätter den gamla i s. Med hur du lägger till en lista till en annan lista:

li.extend(li2)

I detta fall läggs elementen i li2 till de i listan li direkt. Detta då li är ett objekt som  innehåller ett antal element.

Namnen på objekt kallas identifierare då de namnger ett unikt objekt.

Till skillnad mot strängar är listor alltså ändringsbara efter det de skapats. Du kan ändra de ingående elementen i listan.

Övning 2.10
Skriv och testa nedanstående program

lista = [1, 2, 3, 4]
lista[0] = 5
lista[1] = lista[3]
lista[3] lista[3]/2
print(lista)

OBS! Objekt överförs via referens
Den viktigaste skillnaden mellan variabler och objekt är att variabler överförs via värdet och objekt via referens.

Övning 2.11
Skriv in nedanstående program och testa. Notera resultatet. Vad händer här?

s = "Hej"
t = s
t = t + " på dej."
print("Variabler")
print ("s="+s)
print ("t="+t)

li = ["Hej"]
li2 = li
li2.extend(["på","dej"])
print("Objekt")
print ("li="+str(li))
print ("li2="+str(li2))

För strängarna så har s kvar sitt värde ("Hej") när t förändrats. För listobjekten förändras även li när li2 ändras. Det beror på att li2 = li gör att båda identifierarna refererar till samma objekt. Se figuren nedan:


Ovanstående skillnad är speciellt viktigt när du använder objekt som argument i funktioner. Du kan skriva funktioner som gör förändringar i det objekt som ges som funktionsargument. Ex:

Övning 2.12
Följande funktion byter ut element i en lista. Element som är lika med bort byts ut mot element som anges i till

def bytut(li, bort, till):
    #Byter ut elementet i bort mot det i till i listan li
    for i in range(len(li)) :
        if li[i] == bort :
            li[i]=till

lista = [1, 2, 3, 4, 2]          
bytut(lista, 2, 8)
print(lista)

Notera att ingen return-sats behövs i funktionen då den arbetar via referens med listan som ges i argumentet.

Kopior av listor
Ibland vill du ha en kopia av en lista som du kan arbeta med. Alltså skapa ett nytt listobjekt med samma innehåll som det ursprungliga. Då kan du använda en for-sats och iterera över ursprungliga listans element. Följande skapar en ny lista li2 och fyller den med elementen i li:

li2 = []
for e in li : li2.append(e)

Listor och strängar
Listor kan även innehålla strängar och strängar kan omvandlas till listor av tecken.

För att omvandla en sträng till en teckenlista används li = list(s) där s är den sträng som skall delas upp.

För att omvandla en lista med tecken eller strängar till en sträng används s.join(li) där s är ursprungssträgen och li innehåller de tecken som ska läggas till. Följande ger text="abc":

li = ["a", "b", "c"]
text = "".join(li)

Uppgift 2.4
Skriv din egen vändnings-funktion som byter ordningen för elementen i en lista av tal eller strängar. Se nedanstående pseudokod.

def reversera(lista):
    medan index, i, mindre än halva listlängden
        spara temporärt värdet för elementet i från slutet
        sätt värdet på elementet i från slutet till det för i från början
        sätt värdet på elementet i från början till det sparade värdet
        öka i med ett

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.)

tisdag 23 oktober 2012

Eclipse och PyDev

Installera Eclipse

Eclipse är ett professionellt utvecklarverktyg, även kallat IDE - Integrated Development Environment, som används vid programmering i många olika språk. Eclipse är opensource-programvara och fritt att använda.

Ladda ner och installera Eclipse
Du finner Eclipse i många olika versioner beroende på viket språk det i huvudsak är förberett för. Dock kan nya språk läggas till i efterhand vilket vi kommer att göra med Python. Jag rekommenderar att du laddar ner och installerar Eclipse IDE for Java Developers (32 bit).
  • Följ denna instruktion för installation på Mac punkt 1-7
  • Punkt 8 i instruktionen: När programmet första gången startar får du uppmaning att ange "workspace".  Huvudmappen för de filer du skapar i programmet. Ange samma mapp som du redan har dina programmeringsfiler i.
  • Fortsätt med punkt 9-11


Installera PyDev och konfigurera Python

För att programmera Python i Eclipse behöver du installera Python-perspektivet PyDev. Detta görs direkt i Eclipse. Följ instruktionerna på PyDevs hemsida under rubriken Installing with the update site.  Några förtydliganden:
  • Välj som på bilden  http://pydev.org/updates som uppdateringsställe.
  • I fönstret Available Software bockar du för PyDev
  • Så som beskrivs skall du i samma fönster avbocka: Contact all update sites during install to find required software.
Om inget fel uppstår skall du nu ha PyDev installerat

Konfigurera Python
Nu är det dags att konfigurera PyDev så det använder den interpreter du har för Python. (Den du tidigare använt för att köra dina program).
  • I Eclipse väljer du Preferences i menyn Window. Sedan PyDev, Interpreter  - Python.  Samt trycker på New...
  • I dialogrutan som kommer upp skriver du in ett lämpligt namn tex: Python3.2 Sedan trycker du på Browse...
  • På Mac hittar du interpretern här: (Se även denna instruktion)
  • Du bör ha ett fönster som liknar nedanstående efter dessa steg:
  • Tryck Ok
Eclipse ska nu vara färdig för att programmera i Python

Välj PyDev perspektivet
  •  I menyn Window väljer du Open perspective och Other...

  • Tryck Ok och du ska vara klar för att programmera.

Projekt och ett första program

 Då större program består av många filer skapar man projekt där filerna samlas. Skapa ett nytt projekt där du samlar filer du gör i Programmering 1.
  • Tryck på knappen New  och välj PyDev projekt. Se nedan. Tryck Next.
  
  •  Fyll i enligt nedanstående bild och tryck Finish.
  

Nu har du skapat Projektet Programmering 1 och de källkodsfiler (moduler) du skapar kommer att finnas i en undermapp kallad src.

Ett första program
Dags att testa att programmera i Eclipse
  • Högerklicka på ditt projekt (Programmering1) i fönstret till vänster. Välj New och PyDev Module.
  • Fyll i ett namn på modulen, tex: test, och tryck Finish
  • Nu öppnas filen redo för programmering med endast en inledande kommentar inskriven. Kommentaren är av typ docstring, en typ av kommentar som läses av automatiska verktyg som hjälper programmeraren att dokumentera arbetet. Låt den gärna stå kvar.
  •  Under kommentaren skriver du något enkelt program och trycker sedan på pilen i den gröna cirkeln. (Se även bild nedan)
  • Tryck OK i dialogrutan som kommer upp. Du vill köra Python Run alltså vanlig programkörning.
  • Du kan bocka för att automatiskt spara filer före körning så slipper du svara på denna fråga varje gång.
Förhoppningsvis fungerar allt och du får ett resultat som detta:

Slut.