Les og utforsk
Introduksjon
Denne uken skal vi jobbe med funksjoner i Python. Vi har allerede vært innom mange innebygde funksjonene i python, som len()
, max()
, min()
, abs()
, int()
, str()
, float()
, round()
og input()
. Du finner en komplett liste over alle innebygde funksjoner i Pythons dokumentasjon. Det er ikke nødvendig å lese alt dette nå, men det er verdt å bli kjent med dokumentasjonen. Vårt mål denne uken er å lære hvordan vi kan lage og bruke våre egne funksjoner i Python.
Før du kjører koden, anbefales det alltid å ta deg tid til å forstå hva den gjør og hvordan den fungerer.
Syntaks for funksjoner
En funksjon er en sekvens med kommandoer man kan referere til ved hjelp av et funksjonsnavn.
# Vi definerer en funksjon som heter `eksempel_funksjon`
def eksempel_funksjon():
print("A")
print("B")
print("C")
# Vi kaller eksempel_funksjon
eksempel_funksjon()
Funksjoner er veldig nyttige i programmering. Blant annet lar de deg gjenbruke kodeblokker for å redusere repetisjon og feil du kan gjøre mens du programmerer, fordi funksjoner gjør at man kan kjøre samme blokk med kode flere ganger, uten å måtte skrive den samme koden flere ganger.
def eksempel_funksjon():
print("A")
print("B")
print("C")
# Vi kaller eksempel_funksjon tre ganger
eksempel_funksjon()
eksempel_funksjon()
eksempel_funksjon()
En funksjon må være definert før den kalles
find_age() # Krasjer, funksjonen find_age er ikke definert enda
def find_age():
print("Hvilket år ble du født?")
birth_year = int(input())
age = 2022 - birth_year
print(f"Du blir {age} år i år")
Parametre, returverdi og sideeffekter
Funksjoner kan ta input i form av parametre, og kan produsere output i form av både en returverdi og sideeffekter.
# Vi definerer en funksjon som heter `dobling`
# Funksjonen har én parameter (x)
# Funksjonen har returverdi (x * 2)
# Funksjonen har sideeffekt (print skriver til skjermen)
def dobling(x):
print("Jeg dobler nå", x)
return x * 2
# Vi utfører noen kall til dobling-funksjonen.
# Verdiene vi gir som input kalles argumenter.
a = dobling(2)
print(f'dobling av 2 er {a}')
print()
b= dobling(3)+4
print(f'dobling av 3 plus 4 er {b}')
print()
c = dobling(dobling(2))
print(f'dobling av dobling av 2 er {c}')
Funksjoner kan ha så mange parametre vi vil. En parameter er en variabel.
def repeat_print(string, repetitions):
print(string * repetitions)
repeat_print("foo", 3) # skriver ut foofoofoo
def f():
return 42
print(f()) # skriver ut 42
# Merk! Antall argumenter må matche antall parametre!
repeat_print("bar") # krasjer
print(f(1, 2)) # ville også krasjet
Når koden i en funksjon treffer return
, avsluttes funksjonen.
def is_positive(x):
print("Hello!") # kjører
return x > 0
print("Goodbye!") # kjører ikke ("død kode")
print(is_positive(5)) # skriver først Hello, deretter True
Hvis en funksjon ikke utfører en return-setning, returneres den spesielle verdien None
.
def a():
print("Denne funksjonen returnerer None")
return None
print(a()) # None
def b():
print("Denne funksjonen har en tom return-setning")
return
print(b()) # None
def c():
print("Denne funksjonenen har ikke return-setning")
print(c()) # None
Vanlig feil: forveksling av utskrift og returverdi
def cubed(x):
print(x**3) # Funksjon uten retur-verdi, kun side-effekt
cubed(2) # ser ut til å virke
print(cubed(3)) # rart (skriver også ut `None`)
print(2*cubed(4)) # Krasj!
Gjør det heller slik:
def cubed(x):
return x**3 # Funksjonen har retur-verdi, men ingen side-effekt
cubed(2) # ser ikke ut til å virke (hvorfor?)
print(cubed(3)) # funker!
print(2*cubed(4)) # funker!
Skop
En variabel eksisterer i ett skop basert på hvor variabelen ble definert. Hver funksjon har sitt eget skop; variabler som er definert i dette skopet kan ikke nås utenfra.
def foo(x):
print(x)
foo(2) # skriver ut 2
print(x) # Krasjer, siden variabelen x kun var definert i foo sitt skop
def bar():
y = 42
print(y)
bar() # skriver ut 42
print(y) # Krasjer, siden variabelen y kun var definert i bar sitt skop
Det samme variabelnavnet kan eksistere i ulike skop. Men selv om variablene heter det samme, er de helt uavhengig av hverandre.
def f(x):
print("Vi er i f, x =", x)
x += 5
return x
def g(x):
y = f(x*2)
print("Vi er i g, x =", x)
z = f(x*3)
print("Vi er i g, x =", x)
return y + z
print(g(2))
Det kan eksistere flere skop samtidig når koden kjører.
Det globale skopet opprettes når Python begynner å kjøre programmet, og fjernes ikke før Python avslutter.
- Alle variabler som blir definert utenfor en funksjon, befinner seg i det globale skopet.
Hver gang du kaller en funksjon, opprettes et nytt skop som tilhører dette funksjonskallet. Dette kalles et lokalt skop. Det slettes fullstendig når funksjonen returnerer/er ferdig.
- Alle parameterne er variabler som hører til det lokale skopet
- Alle variabler som opprettes i funksjonen tilhører det lokale skopet
Siden du kan kalle én funksjon fra en annen, kan det være mange slike skop “oppå hverandre.”
Det er teknisk sett alltid mulig å se variabler fra det globale skopet, men det er ikke en anbefalt praksis. Dersom vi har en lokal variabel med samme navn, vil den maskere den globale variabelen.
x = "x i globalt skop"
y = "y i globalt skop"
def f():
y = "y i lokalt skop"
z = "z i lokalt skop"
print(x)
print(y)
print(z)
f()
Hold tungen rett i munnen og regn ut hva svaret blir før du kjører koden under. Ta notater på papir for å holde styr på hva som foregår.
def f(x):
print("Vi er i f, x =", x)
x += 7
return round(x / 3)
def g(x):
x *= 10
return 2 * f(x)
def h(x):
x += 3
return f(x+4) + g(x)
print(h(f(1)))
Importering
Noen funksjoner er innebygd i Python, men likevel ikke umiddelbart tilgjengelig; må de importeres fra det som kalles standardbiblioteket.
print(factorial(4)) # vi håper på 4*3*2*1 = 24
# krasjer fordi factorial ikke er importert
#Her henter vi en funksjon for å regne ut fakultet fra math-bibliotektet
from math import factorial
print(factorial(4)) # 24
math
-biblioteket inneholder mange nyttige funksjoner for å utføre matematiske beregninger. La oss se et eksempel hvor vi bruker funksjoner fra dette biblioteket for å regne ut lengden til hypotenusen i en rettvinklet trekant."
# Her henter vi en funksjon for å regne ut kvadratrøtter
from math import sqrt
def hypotenus(katet_1, katet_2):
"""Beregn hypotenusen fra to kateter"""
hyp = sqrt(katet_1 ** 2 + katet_2 ** 2)
return hyp
common_text = "Lengden av hypotenusen på den rettvinklete trekanten med katetlengdene"
print(common_text, "4 og 1 er", hypotenus(4, 1))
a = 3
b = 4
print(f"{common_text} {a} og {b} er {hypotenus(a, b)}")
c = 7
d = 2
print(f"{common_text} {c} og {d} er {hypotenus(c, d)}")
Turtle

Eksperimenter med å justere verdiene til de forskjellige variablene for å se hvordan dette endrer tegningen din for hvilken funksjon du velger å kalle.
from math import sin, cos
import turtle as t
t.speed(0) # adjust speed of turtle, 0 is fastest, 1 is slowest
t.hideturtle()
# single shape
def square(sidelength):
for i in range(4):
t.forward(sidelength)
t.right(90)
def star(num_points, sidelength):
ext_angle = 180 - (180 / num_points)
for i in range(num_points + 1):
t.forward(sidelength)
t.right(ext_angle)
def triangle(sidelength):
for i in range(3):
t.forward(sidelength)
t.left(120)
# chained function to draw many shapes
def many_squares(num_of_shapes):
for i in range(num_of_shapes):
t.setheading(5 * i) # rotate by 5 degrees further with each iteration
square(80) # draw square in rotated position
def spiral_squares(num_of_shapes, sidelength):
for i in range(num_of_shapes):
t.setx(0)
t.sety(0)
t.setheading(5 * i) # rotate by 5 degrees further with each iteration
square(sidelength) # draw square in rotated position
sidelength += 5
def spiral_stars(num_of_shapes, sidelength):
t.color("violet", "light blue")
t.begin_fill()
for i in range(num_of_shapes):
t.setx(0)
t.sety(0)
t.setheading(5 * i)
star(5, sidelength)
sidelength += 5
t.end_fill()
# draw more complex shape
def trefoil(): # amplitude, angular displacement
t.screensize(400, 400, "#005744") # set background color
t.pensize(3) # set width of pen stroke
# experiment with changing these variables - how does the drawing change?
s = 0
a = 80
k = 3
r = 40
linework = "#019879"
# draw expanding trefoil
t.penup()
for i in range(0, 1500):
t.color(linework)
s += 0.01
a += 0.05
x = a * cos(k * s) * cos(s)
y = a * cos(k * s) * sin(s)
t.goto(x, y)
t.pendown()
# draw circle
t.penup()
for i in range(0, 620):
t.color(linework)
s += 0.01
x = r * cos(s)
y = r * sin(s)
t.goto(x, y)
t.pendown()
#### CALL FUNCTION ###
# many_squares(60)
# spiral_stars(60, 5)
trefoil()
t.done()