Observera att denna sida är under utveckling!

Lektion 5: Mer om funktioner.
Denna lektion innehåller Obligatorisk uppgift 1 (OU1)

Moment: Objekt. Parameteröverföring och returvärden.
Begrepp som introduceras: Föränderliga och oföränderliga objekt.
Arbetssätt: Arbeta gärna tillsammans med någon, men skriv egen kod. Diskutera med varandra!

Försök göra övningarna innan du tittar på svaren. Fråga handledarna om det är något svar du inte förstår!

Tips: Använd debuggern

Uppskattad arbetstid: Schemalagd handledningstid inkl redovisning: 6 timmar. Utöver det räkna med eget arbete med lika många timmar.
Redovisning: Obligatorisk redovisning för lärare/handledare enligt tiderna på kurssidan.
Notera att den pythonkod du redovisar skall följa kodningsreglerna
Speciellt:
  • Strukturen på en python-fil: import-satser överst, sedan funktions-definitioner, sist funktionsanrop.
  • Ingen "lös" kod mellan funktions-definitionerna, all lös kod samlas till efter funktions-definitionerna.
  • Rimliga variabelnamn.
  • Inga globala variabler.
  • Utnyttja redan givna funktioner eller funktioner du redan har skrivit

  • Se till att ha legitimation, eftersom redovisningen är en examination
  • Du förklarar din kod individuellt
  • Vad som skulle hända om man gjorde ändringar i koden
  • Vara beredd på frågor från uppgiftstexten
  • Koden måste inte bara fungera, den måste vara tydlig också
  • Vid redovisningarna kan ges extra frågor och kodningsuppgifter
  • Anteckna namnet på personen som du redovisat för!
Backup: När du arbetar på egen dator måste du se till att det löpande görs backup på de filer (py-filer) som du skapar under kursens gång. Om du har filerna enbart lagrade på din dator finns risk att allt försvinner vid ett datorhaveri eller vid stöld.
Samarbete, fusk och plagiat:
  • Muntligt samarbete är tillåtet och rekommenderas.
  • Men den kod du redovisar skall du skriva helt själv, förutom given kod som finns på kursens hemsida.
  • Du får INTE på något sätt dela med mig av kod/svar till någon annan, förutom det muntliga samarbetet.
  • Du får INTE att ta del av kod/svar någon annan på något sätt delar med sig av, förutom det muntliga samarbetet.
  • Vid misstanke om fusk eller plagiat, precis som vid annan examination, kan detta anmälas till universitetets disciplinnämnd.
I denna lektion ska vi exemplifiera mycket av det som togs upp i föregående lektion (funktioner) och dessutom ta upp en del nya saker som har att göra med parametrar och returvärden.

Vad menas med objekt?

I den första lektionen talade vi om "list-objekt" och i den tredje om "turtle-objekt". Det som synligt verkade lite speciellt med dessa var att det fanns metoder för att påverka objekten (append för listor och left, forward m.m. för sköldpaddor). Metoder är funktioner kopplade till individuella objekt.

För att anropa en metod använder man en punktnotation där man framför punkten anger vilket objekt som åsyftas och efter punkten vilken funktion (dvs metod) som avses. Exempel: t.forward(10) som anger att det är just den sköldpadda som t refererar som ska flyttas.

I Python är faktiskt nästan allting objekt (heltal, flyttal, strängar m.m. men även t.ex, funktioner). Det finns alltså metoder knutna även t.ex. till tal.

Det är dock en viktig skillnad mellan å ena sidan t.ex. list- och turtle-objekt och å andra sidan bl.a. heltals- och flyttals-objekt.

Heltals-, flyttals- liksom även t.ex. sträng-objekt är oföränderliga (eng. immutable) medan t.ex. list- och turtle-objekt är föränderliga (eng. mutable). Det har effekter på vad som händer både vid tilldelningar och parameteröverföring.

 

 

im01.png

Vidstående figur illustrerar hur det ser ut när nedanstående kod körts.

t = turtle.Turtle() u = turtle.Turtle() x = 3 y = x

 

 

im02.png

 

 

 

Om vi sedan kör nedanstående rader blir bilden

u = t y = 4

Eftersom heltal är oföränderliga måste y få ett nytt objekt med innehållet 4 (om man kunde ändra 3-an till en 4 skulle även x bli 4 - sannolikt en mycket oönskad effekt...)

Efter tilldelningen u = t kommer u och t att stå för samma objekt. Det innebär alltså att t.ex. t.forward(100) och u.forward(100) gör precis samma sak dvs flyttar på den gröna paddan.

Den röda paddan är borttappad. Den syns (dvs finns) fortfarande men vårt program har svårt att komma åt den.

Vid tilldelning av ett värde av oföränderlig typ till en variabel skapas ett nytt objekt.

Vid tilldelning av ett värde av föränderlig typ till en variabel ändras bara referensen - inget nytt objekt skapas.

Vid funktionsanrop fungerar överföringen av argumenten till parametrarna precis som tilldelningar. Det innebär att om vi skickar ett oföränderligt värde till en parameter så spelar det ingen roll vad funktionen gör med parametern. Om parametern tilldelas ett nytt värde kommer det inte ha någon effekt i den anropande koden.

Om vi skickar ett förändringsbart objekt, t.ex. en turtle, till en funktion så kommer allt funktionen gör med parametern synas (märkas) i den anropande koden.

Återbesök i sköldpaddsdammen

Vi ska nu titta på några funktioner som gör saker med paddor. Det kommer finnas två lite olika typer av funktioner:
  1. Funktioner som ber en viss given padda göra något som det saknas en metod för. Då kan vi skriva en funktion som tar emot en padda som och utför de saker vi vill med den paddan. Om vi själva hade designat paddorna kanska vi hade gjort detta som en metod.
  2. Vi kan också vilja ha paddorna enbart som hjälpmedel för att producera olika geometriska figurer som rektanglar, cirklar, mm. Eftersom vi inte är intresserade av vilken padda som producerar resultatet skickar vi inte med paddan utan låter funktionen själv skapa den! I själva verket behöver vi inte ens veta att funktionen använder paddor för att åstadkomma det vi vill.

Ytterligare turtle-metoder kan vara till nytta i denna lektion

Metod Funktion
xcor() Returnerar paddans x-koordinat.
ycor() Returnerar paddans y-koordinat.
heading() Returnerar paddans kurs. 0 är x-axelns och 90 är y-axelns riktningar.
setheading(angle) Sätter paddans kurs. 0 är x-axelns och 90 är y-axelns riktningar.
towards(x, y) Returnerar riktningen till punkten (xy).
towards(t) Returnerar riktningen till paddan t.
distance(x, y) Returnerar paddans avstånd till punkten (xy).
distance(t) Returnerar avståndet från den egna paddan till paddan t.

Turtlar som parametrar

Om man vill flytta en padda utan att den ritar ett spår är följande funktion användbar:
# Funktionen har tre parametrar: # Paddan t och en position dit paddan skall flyttas def jump(t, x, y): t.penup() # lyft pennan som ritar paddans spår t.goto(x, y) # Flytta paddan till (x,y) t.pendown() # sänk pennan så att den ritar spår
Funktionen tar alltså emot en padda (eller, mer exakt uttryckt, en referens till ett padd-objekt), lyfter dess penna, går till den angivna positionen och sätter ned pennan.

Turtlar som funktionsvärde

Exempel: make_turtle

När man skapar en padda med turtle.Turtle() placeras paddan i origo. Om det är vanligt att vilja ge den en annan startposition kan vi använda:
# Funktionen har två parametrar som # beskriver en position där en padda # skall skapas. Paddan returneras. def make_turtle(x, y): t = turtle.Turtle() # Skapa en padda jump(t, x, y) # Flytta paddan till (x,y) return t # Returnera paddan
Dessa behövs för att kunna använda turtlar och slumptal.

Övningar

  1. Skriv en funktion rectangle(x, y, width, height, color) som skapar en padda och målar en rektangel med angiven bredd, höjd och färg. Rektangelns nedre vänstra hörn ska vara i punkten (x, y). Du behöver göra import turtle i programmet för att kunna använda turtlar. Lösningsförslag
    # Funktionen ritar en rektangel, fyller den med en färg.
    # Nedre vänstra punkt för rektangeln bestäms av (x,y)
    # Rektangelns storlek bestäms av parameterna width och height. 
    # Färgen bestäms av parametern color.
    def rectangle(x, y, width, height, color):
        t = make_turtle(x, y)  # Skapa en padda t i (x,y)
        t.hideturtle()         # Gör paddan osynlig
        t.fillcolor(color)     # Bestäm fyllnadsfärgen för den rektangeln
        t.begin_fill()         # Definierar starten för själva fyllandet
        # En loop som bestäms av innehållet i en lista:
        # Loopen går fyra varv och dist kommer ha följande värden:
        # width, height, width, height (i tur och ordning)
        for dist in [width, height, width, height]:
            t.forward(dist)    # Flytta paddan (och rita dess spår) en sträcka dist
            t.left(90)         # rotera paddan åt vänster 90 grader
        t.end_fill()           # Definierar slutet för själva fyllandet
    
  2. La Tricolore

    Skriv en funktion tricolore(x, y, h) som ritar en fransk flagga med nedre vänstra hörnet i punkten (x, y) och höjden h. Proportionerna ska vara 2:3.

     

    Lösningsförslag
    # Funktionen ritar en flagga som består av tre fyllda rektanglar.
    # Parametrarna x och y bestämmer flaggans nedre vänstra hörn.
    # Parametern h bestämmer flaggans höjd och bredd.
    def tricolore(x, y, h):
        w = h/2  	                     # färgfältens bredd
        rectangle(x, y, w, h, 'blue')    # vänstra fältet
        rectangle(x+w, y, w, h, 'white') # mittersta fältet
        rectangle(x+2*w, y, w, h, 'red') # högra fältet
    
  3. pentagram

    Skriv funktionen pentagram(x, y, side) som skapar en padda och ritar ett pentagram. Toppen ska placeras i punkten (x, y). Parametern side anger längden på linjerna mellan spetsarna..

    Tips: Vinkeln i toppen är 36 grader.

     

    Lösningsförslag
    # Funktionen ritar en pentagram.
    # Tre parametrar: En position för övre spetsen
    # och längden för varje raksträcka.
    def pentagram(x, y, side):
        t = make_turtle(x, y)     # Skapa en padda t i (x,y)
        t.hideturtle()            # Gör själva paddan osynlig
        t.setheading(270 - 36/2)  # Rikta paddans kropp i denna riktning
        # En loop som går fem varv, som ritar en sträcka i varje varv
        for i in range(5):        
            t.forward(side)       # Flytta paddan (rita spåret) sträckan side
            t.left(180-36)        # Rotera paddan 180-36 grader
    

Nu följer de obligatoriska uppgifterna som skall redovisas, nämligen uppgift A-C

Notera att den pythonkod du redovisar skall följa kodningsreglerna

Uppgift A: Prova funktionerna!

Uppgift 1
Lägg in ovanstående funktioner (jump, make_turtle, rectangle, tricolore och pentagram) i en Python-fil. Modifiera pentagram så att den tar emot en parameter för fyllnadsfärg på samma sätt som rectangle. Skriv de rader som producerar vidstående resultat. Lägg in den kod som anropar funktionerna samlat sist i python-filen. Tänk på att utnyttja de funktioner som finns. Du ser av figuren som skall produceras att en flagga skall ritas omgärdad av pentagram. Den anropande koden bör givetvis "göra så lite som möjligt själv", och istället anropa den funktioner som löser det hela. Du har själv skrivit dessa funktioner i ovan övningar (2 och 3).
Kommentar:Färgfyllningen av pentagrammen kan bero på vilken dator/operativsystem du använder. Mac-dator fyller ej i mitten av pentagrammet. Det är alltså inget du behöver fixa, utan det är okej att stjärnorna ser ut som dom gör.

Tips:

  1. Om du ger paddan hastigheten 0 (t.speed(0)) så går det fortare att rita!
  2. Du kan sätta valfri färg på pentagrammen
  3. Det kan räcka med tre rader kod för att rita de 10 pentagrammen. Givetvis skall du använda funktionen pentagram) som ritar ett pentagram.
    Tips: Använd for-satser. Tänk på att programmet skall rita identiska pentagrammer i 10 st olika positioner. Den övre raden består av 5 st pentagrammer (de är bara förskjutna i x-led). Den undre raden är nästan identisk med den övre, skillnaden är en annan y-koordinat

Default-värden på parametrar

Man kan ge parametrar standardvärden ("default-värden") som gäller om man utelämnar den.

Exempel: Om man deklarerar rectangle-funktionen så här:
def rectangle(x, y, width, height, color=''):
så kan man anropa den så här:
rectangle(0, 0, 50, 50) En ofylld kvadrat (en tom sträng som fyllnadsfärg anger att ingen fyllnad ska ske)
rectangle(100, 100, 50, 50, 'blue') En kvadrat fylld med blå färg.
rectangle(100, 100, 50, 50, color='red') En kvadrat fylld med röd färg. Är ett bra sätt om man har flera parametrar med default-värden.

Övningar

  1. Lägg till en parameter visible till funktionen make_turtle med defaultvärdet True. Anropet make_turtle(x, y) ska, som tidigare, skapa en synlig padda medan anropet make_turtle(x, y, visible=False) liksom makeTurtle(False) ska returnera en osynlig padda. Sätt också alltid osynliga paddors hastighet till högsta möjliga med speed(0). Lösningsförslag
    def make_turtle(x, y, visible = True):
        t = turtle.Turtle()
        if not visible:
            t.hideturtle()
            t.speed(0)
        jump(t, x, y)
        return t
    
  2. Skriv funktionen random_turtle(side) som skapar en padda, flyttar den till en slumpmässig plats i en centrerad kvadrat med sidan side. Paddan ska få en slumpmässig riktning mellan och och 359. Parametern side ska ha defaultvärdet 500. Tänk på att programmet måste ha import random för att kunna använda slumptal. Lösningsförslag
    def random_turtle(side=500): low = -side//2 high = side//2 t = make_turtle(random.randint(low, high), random.randint(low, high)) t.setheading(random.randint(0, 359)) return t

Uppgift B: Rita flaggor

flag
Skriv en funktion vietnamese_flag(x, y, height) som ritar den vietnamesiska flaggan med nedre vänstra hörnet i punkten (x, y). Parametern height anger höjden på flaggan och flaggans proportioner är 3:2. Pentagrammet ska vara centrerat på flagga. Uppskatta storleken på pentagrammet (eller leta upp rätt värde på nätet).

Ledning: Du måste antagligen skriva om pentagram-funktionen dels för att du inte ska ha med kantlinjerna och dels för att hela det inre ska vara färgat.
Kommentar:
Färgfyllningen av pentagrammen kan bero på vilken dator/operativsystem du använder. Mac fyller ej i mitten av pentagrammet. Det är alltså inget du behöver fixa, utan det är okej att stjärnorna ser ut som dom gör.

Du kan välja någon annan flagga t.ex. den amerikanska, som också består ju också av rektanglar och fyllda pentagram. Den flagga du väljer måste bestå av något mer än rektanglar! Lägg den kod som anropar funktionen vietnamese_flag(x, y, height) samlat sist i python-filen.
Tänk på att utnyttja de funktioner du skrivit.

Uppgift C: Irrande paddor

  1. Skapa filen dizzyTurtles.py.
  2. Lägg in raderna
    import turtle import random
    först i filen. Dessa behövs för att kunna använda turtlar och slumptal.
  3. Lägg in funktionerna jump, rectangle och make_turtle i filen.
  4. Skriv funktionen move_random(t) som skall göra en slumpmässig förflyttning av paddan.

    Kursen ska ändras med med ett slumpmässigt värde i intervallet [-45, 45]. Om t.ex. paddan har kurs 90 ska kursen sluta i intervallet [45, 135]. Därefter ska paddan gå framåt. Längden på sträckan som paddan går ska vara ett slumptal i intervallet [0, 25].

    För att skapa slumpvärden ska funktionen random.randint(m, n) användas. Den returnerar ett slumptal mellan m och n (gränserna kan antas).

  5. bild1

    Skriv nu anropande kod som skapar en padda, ritar en centrerad kvadrat med metoden rectangle. Kvadraten ska ha sidan 500 och fyllas men någon läcker färg (t.ex. 'lightblue'). Notera att denna kod skall ligga längst ned i filen, efter alla funktionsdefinitioner.

  6. Flytta paddan (jump) till en slumpmässig position inuti den blåa rutan. Tips. Använd inbyggda funktionen random.randint(...) för att slumpa fram en position innanför kvadraten. Nu kan det se ut så här:

  7. bild2

    Lägg till kod som med hjälp av en for-sats gör 250 anrop till move_random. Notera, denna funktion skall ej ändras, utan den skall fortfarande flytta en padda slumpmässigt en liten sträcka.

    Då kan det se ut så här:

  8. bild3

    Modifiera koden i funktionen move_random som gör så att om paddan efter förflyttningen befinner sig utanför den blå rutan vänder sig mot origo. (Ett annat sätt att lösa "studsen" mot kanten kunde vara att låta utgående vinkel sättas till ingående vinkel. Om paddan går in i kanten med 20 graders vinkel, skall den gå ut med samma vinkel. Detta är dock lite svårare att få till)
    Tips: Med metoderna xcor respektive ycor kan man få veta en paddas x- och y-koordinat. Om t är en padda:
    x = t.xcor() # x blir paddans x-koordinat
    y = t.ycor() # y blir paddans y-koordinat

    Då kan det se ut så här:

  9. bild4

    Modifiera den anropande koden så att den skapar ytterligare en padda som också ska placeras ut slumpmässigt. Ge paddorna olika färg (metoden color).

    Modifiera for-satsen så att den i varje varv flyttar slumpmässigt (med funktionen move_random), först den ena paddan och sedan den andra paddan, dvs två anrop av funktionen move_random. Låt loopen snurra 500 varv. Notera att funktionen move_random skall ej ändras, dvs den skall fortfarande flytta EN padda.

    Modifiera den anropande koden: Låt den ena paddan skriva ut texten 'close' i fönstret om de är närmare varandra än 50 punkter. Metoden write hjälper oss med detta. Exempel: t.write('close') skriver ut texten 'close' intill paddan t i fönstret. Du kanske måste köra programmet många ggr för att paddorna skall komma nära varandra. Eller låta loopen gå fler än 500 varv.
    Tips: Använd metoderna xcor respektive ycor för att ta reda på en paddas position.

    Låt också programmet (anropande kod) räkna och sedan skriva ut hur många gånger det var nära. Testkör programmet.

  10. Extra frivillig uppgift: Lägg all anropande kod som du skrivit i pkt 5-9 i en ny funktion. Fundera på om funktionen behöver ha någon parameter och om den behöver returnera något. Övriga funktioner skall vara oförändrade. Efter denna nya funktion, gör ett anrop av den och kör hela programmet. Det bör fungera på samma sätt som i pkt 9.

Allmänna frågor

  1. Vilka datatyper har du hittills sett i Python? Svar
    int, float, str, bool, list, tuple och turtle
  2. Vad är det för skillnad på uttrycken 2 och "2"? Svar
    Den första har typen int och den andra typen str.
  3. Vad skrivs ut av satsen print(int(1.8))? Svar
    Prova och förklara resultatet!
  4. Hur gör man för att se vilka funktioner som finns i modulen math? Visa! Svar
    dir(math)
  5. Vad är skillnaden mellan en funktion och en metod? Svar
    En metod hör till ett objekt vilket inte en funktion (normalt) gör.
  6. Vad är en parameter? Svar
    En parameter är en variabel som nämns i funktionsdefinitionen. När funktionen anropas får parametern värde från motsvarande argument.

Fråga

Hur många timmar har du hittills arbetat vid dator för denna kurs?


Gå till nästa lektion eller gå tillbaka