Funksjoner#
Læringsutbytte
Etter å ha arbeidet med dette temaet, skal du kunne:
bruke funksjoner til å strukturere og gjenbruke kode.
forklare hva som menes med globale og lokale variabler.
Definisjon#
I tillegg til innebygde funksjoner i Python som print og input kan vi lage funksjoner selv. Dette kan være svært nyttig fordi det kan gjøre programmet mer oversiktlig og håndterbart. I tillegg er det nyttig med funksjoner når vi skal gjøre samme ting flere ganger. Si at vi for eksempel har en vilkårlig matematisk funksjon \(f(x) = x^2 + x - 5\). Dersom vi vil regne ut \(f(x)\) for alle heltallsverdier av \(x\) mellom 1 og 50, kan vi gjøre dette med funksjoner. Først definerer vi funksjonen:
def f(x):
return x**2 + x - 5
Vi definerer her en funksjon med kodeordet def og gir den et funksjonsnavn, her f. Deretter spesifiserer vi hva inn-verdien/variabelen til funksjonen skal hete i parentes. Her kaller vi den x. I programmering kaller vi en slik størrelse for en parameter. Gitt én verdi av x, skal funksjonen returnere (spesifisert ved return-kommandoen) en funksjonsverdi. Legg merke til at syntaksen er ganske lik vilkår (if-tester), while- og for-løkker, med et kolon etter funksjonsnavnet og innrykk på alt som tilhører funksjonen.
Vi får derimot ikke noe output av å definere en funksjon. For å få et output, må vi bruke (vi sier også “kalle på”) funksjonen:
funksjonsverdi = f(2) # Kaller på funksjonen
print(funksjonsverdi)
# Eller
print(f(2)) # Kaller på funksjonen inni en print-funksjon
1
1
Underveisoppgave
Lag en Python-funksjon som representerer den matematiske funksjonen \(f(x) = \frac{-x}{2} + \sqrt{x}\). Lag ei løkke som skriver ut 100 ulike funksjonsverdier.
Løsningsforslag
import numpy as np
def f(x):
return -x/2 + np.sqrt(x)
for x in range(100):
print(f(x))
Vi kan også lage funksjoner uten returverdi, for eksempel funksjoner som skriver ut noe:
# Definerer to funksjoner
def f(x):
print(x**2 + x - 5)
def gratulerer(navn):
print("Gratulerer med dagen,", navn)
# Kaller på funksjonene
f(2)
gratulerer("Silje")
1
Gratulerer med dagen, Silje
Her ser vi at vi ikke trenger å skrive print når vi kaller på funksjonene. Dette ser da enda enklere ut enn å bruke retur-verdier, så hvorfor bruker vi return i det hele tatt?
Det er faktisk bedre å bruke return enn print, der det er mulig. Hvis vi for eksempel er interessert i å gjøre noe annet med funksjonsverdiene enn å printe dem, må vi ha konkrete verdier å jobbe med. La oss si at vi ønsker å finne differansen mellom to funksjonsverdier. Hvis vi skal regne med funksjonsverdier, må vi ha en returverdi. Det fungerer nemlig ikke å trekke fra hverandre to print-funksjoner. Eksempelet nedenfor illustrerer dette.
Vi kan også representere matematiske formler som Python-funksjoner, for eksempel slik:
import numpy as np
def areal_sirkel(r):
A = np.pi*r**2
return A
def volum_sylinder(r, h):
V = np.pi*r**2*h
return V
Vi kan også skrive np.pi*r**2 og np.pi*r**2*h direkte etter return i funksjonene ovenfor, istedenfor å gjøre det på to linjer. Dette er litt smak og behag, men ofte kan det være mer oversiktlig å gjøre ting på flere linjer enn på én. Dessuten kan man skrive formelen direkte slik den forekommer i matematikken.
Underveisoppgave
Volumet til ei kule er gitt ved \(\frac{4}{3}\pi r^3\). Lag en funksjon som beregner dette volumet og finner differansen mellom volumet til ei kule med radius 10 og ei kule med radius 5.
Løsningsforslag
import numpy as np
def volum_kule(r):
V = (4/3)*np.pi*r**3
return V
volumforskjell = volum_kule(10) - volum_kule(5)
Her ser vi også at den siste funksjonen tar to parametre. Det er mulig å bruke så mange parametre i en funksjon som du ønsker. Det går også an å lage funksjoner uten parametre, for eksempel slik:
def hei():
print("Hei på deg!")
hei()
Hei på deg!
Funksjoner med flere returverdier#
I motsetning til funksjoner i matematikk kan en funksjon i programmering ha flere retur-verdier. Disse kan vi tilordne til variabler adskilt med komma, som vist nedenfor.
Underveisoppgave
Forklar hvordan programmet ovenfor fungerer. Modifiser programmet slik at det også returnerer renta, og skriv ut “Det tar {tid} år før du har {penger} kroner i banken med en rente på {renter*100} prosent.”
Lokale og globale variabler**#
Hva skjer hvis vi ikke returnerer verdier i funksjonen ovenfor? Vil vi uansett kunne printe renta og antallet år? La oss undersøke dette.
def penger_i_banken(startkapital, sluttkapital, renter):
kapital = startkapital
år = 0
while kapital <= sluttkapital:
kapital = kapital + kapital*renter
år = år + 1
return kapital
penger = penger_i_banken(1000, 3000, 0.01)
print("Det tar", år, "år før du har", round(penger,2), "kroner med en rente på", renter*100, "prosent")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_39764/3569527658.py in <module>
8
9 penger = penger_i_banken(1000, 3000, 0.01)
---> 10 print("Det tar", år, "år før du har", round(penger,2), "kroner med en rente på", renter*100, "prosent")
NameError: name 'år' is not defined
Her får vi visst en feilmelding, selv om vi klart kan se at “år” er definert som en variabel inni funksjonen. Dette handler om at alle variabler som defineres i en funksjon, kun er tilgjengelig inni denne funksjonen. De kalles derfor lokale variabler. Variabler som er definert utenfor funksjoner, kaller vi da for globale variabler. Disse er tilgjengelig både inni og utenfor en funksjon. Her er to eksempler som viser dette:
def funksjon():
print(a)
a = "Her er jeg!"
funksjon()
print(a) # Skriver ut den globale variabelen a
Her er jeg!
Her er jeg!
def funksjon():
b = "Her er jeg!" # b defineres lokalt inni funksjonen
print(b)
funksjon()
print(b) # Prøver å skrive ut den lokale variabelen. Vi får dermed en feilmelding
Her er jeg!
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-36-9fcd0c311f14> in <module>
4
5 funksjon()
----> 6 print(b) # Prøver å skrive ut den lokale variabelen. Vi får dermed en feilmelding
NameError: name 'b' is not defined
Vi kan gjøre en lokal variabel til en global variabel, dersom vi trenger det. Dette er ikke vanlig så vanlig å gjøre, men vi kan gjøre det slik:
def masseenergi(m):
global c
c = 3E8 # lyshastigheten i m/s
E = m*c**2
return E
print("Energien til legemet er:", masseenergi(1), "joule.")
print("Lysets hastighet i vakuum:", c, "m/s.")
Energien til legemet er: 9e+16 joule.
Lysets hastighet i vakuum: 300000000.0 m/s.
Undervisningstips
Funksjoner føles abstrakt for mange. Det kan spesielt være vanskelig å forstå forskjellen på å definere og å kalle på en funksjon. Derfor bør en ikke introdusere for mange konsepter samtidig. I mange tilfeller kan vi klare oss fint uten funksjoner også, og da bør vi unngå dem - husk at det realfaglige innholdet er det viktigste, ikke det kodetekniske. Mange løsninger du finner på internett, vil inneholde funksjoner. Dette er det mest riktige rent kodeteknisk, men husk å ta en pedagogisk overveielse på om det er nødvendig i det gitte tilfellet.
Her er noen tips for å undervise funksjoner:
Noen elever definerer funksjoner inni løkker. Det er det samme som å definere den samme variabelen et visst antall ganger. Vi trenger ikke å minne datamaskinene på hva funksjonen er! Derfor defineres funksjoner kun én gang. Vi kan derimot kalle på (bruke) funksjonen inni ei løkke. Men da er funksjonen definert utenfor, et annet sted i programmet.
Når programmet leser definisjonen av funksjonen, kjører den ikke funksjonen. Det er derfor likegyldig hvor funksjonen står, så lenge den står før den brukes et sted. Noen elever tror at funksjonen brukes når den defineres. Vis at vi ikke får noe output i et program der en funksjon defineres (med mindre funksjonen printer noe).
Mange elever glemmer “return”. Dette gir ofte feil som inneholder “NoneType”. Her er et eksempel:
def f(x):
x**2
def g(x):
return x - 2
print(f(1) - g(2))
Det er vanskelig å forstå at variablene som defineres inni funksjonen ikke er tilgjengelig utenfor funksjonen, med mindre de returneres og legges i en variabel. Dette handler om lokale og globale variabler som vi beskrev ovenfor. Vi bør minne elevene på at variabler som defineres inni funksjoner, ikke finnes utenfor funksjonene.
Vi trenger ikke å definere variablene på forhånd i et program, slik vi er vant til. Vi kan bare mate dem rett inn i funksjonen, for eksempel slik:
def areal_sirkel(r):
pi = 3.14
return pi*r**2
print(area_sirkel(2)) # Vi trenger ikke å skrive r = 2 i starten av programmet
Parameternavn brukes bare lokalt i funksjonen. Vi trenger altså ikke å
def f(g,a,b):
return a*x + g(b)
def h(x):
return x/2
q = 1
print(f(h,q,1))
Når vi kaller på funksjonen f og putter h og q inn i funksjonen, putter vi bare verdiene til h og q inn. Funksjonen f kaller disse parameterne g og a, og setter g lik verdien til h, a lik_ verdien til q og b lik 1. Dette kan være forvirrende, og en måte å unngå problemet i startfasen, er å bruke samme parameternavn i funksjonen som det man faktisk forer inn i funksjonen (selv om vi jo faktisk gir b en verdi direkte her):
def f(g,a,b):
return a*x + g(b)
def g(x):
return x/2
a = 1
print(f(g,a,1))
Begynn med funksjoner som returner noe og som har parametre. Funksjoner uten parametre og funksjoner som ikke returnerer noe, kan eventuelt vente.
Vi minner om: Funksjoner er vanskelig for mange! Hvis mulig, unngå dem gjerne.
Oppgaver#
Oppgave 5.1
Forklar hvordan programmet nedenfor fungerer.
def f(x):
return x + 1
addisjon = f(1) + f(3)
subtraksjon = f(1) - f(3)
print(addisjon, subtraksjon)
Løsningsforslag
Vi definerer først en funksjon f som skal returnere funksjonsverdien x + 1. Deretter kaller vi på (bruker) funksjonen ved å beregne summen av f(1) og f(3) og differansen mellom de samme funksjonsverdiene. Da henter programmet informasjon fra funksjonen ovenfor, og beregner slik: addisjon = (1 + 1) + (3 + 1) = 6 og subtraksjon = (1 + 1) - (3 + 1) = -1. Resultatene fra dette skrives så ut.
Oppgave 5.2
I programmet nedenfor definerer vi en funksjon som regner ut volumet til en sylinder. Lag en annen funksjon i samme program som regner ut volumet til ei kule.
(\(V_{kule} = \frac{4}{3}\pi r^3\))
Løsningsforslag
from numpy import pi
def volum_kule(r):
V = 4/3*pi*r**3
return V
# Tester funksjonen
print(volum_kule(2))
Oppgave 5.3
Hvert program i denne oppgava inneholder noen feil. Finn feilene og rett på dem slik at programmene kan kjøres korrekt.
Funksjonen skal regne ut \(f(x) = \frac{1}{2x} + 1\) og returnere svaret. I programmet skal funksjonen kalles på for \(x = 4\):
def f(x):
1/2*x + 1
print("f(x) = ",f(x))
Programmet ber brukeren om å skrive en verdi for x og regner ut \(f(x) = 3x + \cos(x)\):
def f(x):
return 3x + cos(x)
y = input("Skriv inn verdi for x i radianer: ")
print("f(x) =",f(y))
Programmet skal skrive ut funksjonsverdien G(1).
def G(t):
a = t**2 - 2
return a
t = 1
print(a)
Løsningsforslag
Uttrykket \(1/2*x + 1\) regner ut \(f(x) = x + 1\), og ikke den ønskede funksjonen. For at programmet skal regne ut hva x blir i den ønskede funksjonen, må parentes brukes i uttrykket for nevneren. Variabelen x er heller ikke definert. Variabelen kan settes til å være lik 4. Vi kan også kalle funksjonen direkte med f(4).
def f(x):
return 1/(2* x) + 1
print("f(x) = ",f(4))
Her må cosinus importeres fra et passende bibliotek. Vi må også ha et innrykk på return i \(f(x)\), fordi return tilhører funksjonen. Leddet \(3x\) må omskrives til \(3*x\). Til slutt må variabelen \(y\) omgjøres til float for at programmet skal kunne gjøre flytallsoperasjoner på den gitte verdien fra brukeren.
from numpy import cos
def f(x):
return 3*x + cos (x)
y = float(input(" Skriv inn verdi for x i radianer: "))
print("f(x) =",f(y))
For å finne hva funksjonsverdien til G, må vi huske å kalle på funksjonen:
def G(t):
a = t**2 - 1
return a
t = 1
print(G(t))
Oppgave 5.4
Lag et program eller flere programmer som bruker funksjoner til å regne ut:
Arealet til en sirkel.
Radius til en sirkel gitt arealet.
Omkretsen til en sirkel.
Volumet til ei kule.
Overflatearealet til ei kule.
Du kan lage en enkel versjon først uten funksjoner. Lag så en versjon som inneholder funksjoner av hver av formlene. Ikke ta input fra brukeren, men sett verdiene direkte inn i funksjonskallene.
Løsningsforslag
from numpy import pi
# 1
def sirkel_areal(r):
return pi*r**2
# 2
def sirkel_radius(A):
return (A/pi)**0.5 # Opphøyer i 0.5 eller kan bruke sqrt fra numpy
# 3
def sirkel_omkrets(r):
return 2*pi*r
# 4
def kule_volum (r):
return 4/3*pi*r**3
# 5
def kule_overflate (r):
return 4*pi*r**2
Oppgave 5.5
Forklar hvorfor programmet under gir None som output.
def f(x):
x = 2*x
x = 12
x = x + 12
x = f(x)
print(x)
Løsningsforslag
Verdien til x blir None fordi funksjonen f ikke returner en verdi. For å sørge for at x får en tallverdi etter å ha kalt på f, må f returnere noe – i dette tilfellet et tall.
def f(x):
return 2*x
x = 12
x = x + 12
x = f(x)
print(x)
Oppgave 5.6
Karvonens formel kan brukes til å finne pulsen til en person gitt hvilepuls \(H_{hvile}\) og treningsintensitet \(p\) (i prosent):
\(hjerteslag \ per \ minutt = \left(H_{maks} - H_{hvile}\right)\cdot\frac{p}{100} + H_{hvile}\)
der \(H_{maks}\) er maks antall hjerteslag personen kan ha. Den maksimale pulsen kan en finne ved \(H_{maks} = 220 - \textit{alder til person}\). Lag et program som regner ut pulsen til en 20 år gammel person som trener med 60 % intensitet og hvilepuls på \(70\) slag per minutt. Lag Karvonens formel som en funksjon.
Løsningsforslag
def karvonen(hvilepuls, intensitet, alder):
p = intensitet
maks = 220 - alder
puls = (maks - hvilepuls)*p/100 + hvilepuls
return puls
puls = karvonen(70, 60, 20)
print(" Personen vil ha en puls på",puls )
Oppgave 5.7 (kjemi)
I kjemi har vi ofte bruk for molregning. Lag et enkelt program som regner ut antall mol dersom brukeren taster inn molmasse og masse av et bestemt stoff. Du kan også be brukeren taste inn stoffet det gjelder, slik at du får dette som output også. Lag formelen som en funksjon.
Løsningsforslag
def antall_mol (masse , molmasse ):
return masse/molmasse
stoff = input(" Hvilket stoff vil du finne antall mol til ?: ")
masse = float(input(" Skriv inn massen ( gram ): "))
molmasse = float(input(" Skriv inn molmassen ( gram /mol): "))
mol = antall_mol (masse , molmasse )
print("Stoffet", stoff, "består av", mol ,"mol.")
Oppgave 5.8 (kjemi)
Lag et program som regner ut pH fra \([H_3O^+]\) ved hjelp av en funksjon.
Løsningsforslag
from numpy import log10
def ph_H3O(konsentrasjon):
return -log10 (konsentrasjon)
ph = ph_H3O(1E-5)
print("pH av den gitte konsentrasjonen er:", ph)
Oppgave 5.9 (fysikk)
Programmer én av bevegelsesformlene (kinematikklikningene) som en funksjon. Du kan selv velge hva programmet skal regne ut.
Løsningsforslag
def posisjon(v0 , a, t):
return v0 + a*t
v = posisjon(2, 10, 5) # Tester funksjonen med v0 = 2, a = 10 og t = 5.
print("Farten til legemet er:", v, "m/s.")
Oppgave 5.10 (fysikk)
Bruk Bohrs formel for spektrene til hydrogenatomet: \(f =\frac{B}{h}\cdot \left( \frac{1}{m^2} - \frac{1}{n^2} \right)\)
Lag et program som regner ut bølgelengden til fotonet som emitteres når et elektron deeksiterer fra skall m til n. Bruk en funksjon.
Husk at vi har følgende sammenheng mellom frekvens og bølgelengde (\(\lambda\)):
\(\lambda = \frac{c}{f}\)
\(B = 2.18\cdot10^{-18}\), \(c = 3.00\cdot10^8\) m/s og \(h = 6.63\cdot10^{-34}\).
Løsningsforslag
# Konstanter
B = 2.18E-18
h = 6.636E-34
c = 3e8
#Bohrs formel
def Bohr(n,m):
f = B/h *(1/ m**2 - 1/n **2)
bl = c/f # bølgelengde i meter
bl_nm = bl*1E9 # bølgelengde i nanometer
return bl_nm
#Energinivåer
n = int(input("Skriv inn en verdi for n:")) #skallet det eksiteres fra
m = int(input("Skriv inn en verdi for m:")) #skallet det eksiteres til
print("Bølgelengden til lyset fra n =",n ,"til m =", m,
"er:", round(Bohr(n,m)),"nm")
Oppgave 5.11 (matematikk)
Lag en funksjon som tar tre variabler a, b og c, tilsvarende koeffisientene i andregradsfunksjoner av typen \(f(x) = ax^2 + bx + c\). La funksjonen løse andregradslikninger av typen \(f(x) = 0\) ved hjelp av andregradsformelen.
Løsningsforslag
def andregradsformelen(a, b, c):
rotuttrykk = b**2 - 4*a*c
if rotuttrykk > 0:
x1 = (-b + rotuttrykk**0.5)/(2*a)
x2 = (-b - rotuttrykk**0.5)/(2*a)
return x1, x2
elif rotuttrykk < 0:
return "Likningen har ingen reelle løsninger."
elif rotuttrykk == 0:
x = -b/(2*a)
return x
print(andregradsformelen(1, 2, 3))
print(andregradsformelen(1, -2, 1))
print(andregradsformelen(1, -4, 3))
Oppgave 5.12
Hvorfor har x samme verdi før og etter funksjonen f har blitt kalt på i programmet under?
def f(x):
x = x + 3
return 9*x
x = 3
print(x) # Skriver ut 3
y = f(x)
print(x) # Skriver ut 3
Løsningsforslag
$_x_$ er en global variabel utenfor funksjonen. Den får verdien 3. I tillegg finnes det en lokal variabel med samme navn inni funksjonen. Denne variabelen får verdien $_x = x + 3 = 3 + 3 = 6_$, men denne variabelen er ikke tilgjengelig utenfor funksjonen.
Oppgave 5.13
De fleste gasser kan modelleres med tilstandslikninga for idelle gasser:
\(PV = nRT\)
der P er trykket i pascal, V er volumet i kubikkmeter, n er stoffmengden i mol, \(R = 8.3144598 J/(mol\cdot K)\) er gasskonstanten og T er temperaturen i Kelvin.
Lag et program der du bruker denne likninga til å lage en funksjon for P og en annen for T. Test funksjonene.
Løsningsforslag
def trykk(V, n, T):
R = 8.3144598 # J/(mol*K)
P = n*R*T/V
return P
def temperatur(P, V, n):
R = 8.3144598 # J/(mol*K)
T = P*V/(n*R)
return T
print(trykk(100, 1, 300))
print(temperatur(100, 1, 1))
Oppgave 5.14*
Studer programmet nedenfor. Hvilke variabler er lokale, og hvilke er globale? Hva skrives ut?
def f(x,y):
global e
e = x + y + e
return e
c = 1
d = 2
e = 3
print(f(c, d) + e)
Løsningsforslag
Variablene c_, d og e er globale variabler, mens x og y er lokale variabler som kun eksisterer inni funksjonen. Når vi printer f(c, d) + e, overføres verdien av c og d til de lokale variablene x og y i funksjonen. Deretter beregnes e ved hjelp av x, y og den globale e, som har verdien 3. Variabelen e fra funksjonen (nå med verdien 6) defineres som global, og overskriver dermed den tidligere e (med verdien 3). Det er denne e-en som legges til f(c, d) i print-kommandoen til slutt.
Filmer#
I videoen nedenfor kan du få en innføring eller repetisjon i den grunnleggende teorien bak funksjoner.