Uke 3 — functions / def / return ================================ Introduksjon ------------ Denne uken skal vi jobbe med funksjoner i Python. Enten kan man definere sine egne funksjoner eller så kan man bruke innebygde funksjoner i Python. Du finner en liste på Pythons innebygde funksjoner i `Pythons dokumentasjon `_. Det er vel verdt å bli kjent med dokumentasjonen. Hvis du ikke kan en funksjon fra før, kan du søke den opp her og finne ut hva den gjør. Det er ikke nødvendig å lese alt dette nå, men å lese på de funksjonene du har bruk for. For nå kan det være lurt å lese på funksjonene ``len()``, ``max()``, ``min()``, ``abs()``, ``int()``, ``str()``, ``float()`` og ``input()``. Eksempler --------- Eksempel 0 .......... Før vi begynner med funksjoner, litt om variabler. En variabel lagrer verdier slik at vi kan bruke dem igjen seinere. Her er et lite eksempel: Last ned filen her: :download:`eksempel_0.py`. .. literalinclude:: eksempel_0.py Hva er forskjellen på x og y? Hvis vi skal bruke ``50`` igjen seinere i programmet, burde vi se på ``x`` eller ``y``? For å se hva som skjer når koden kjøres kan du prøve å skrive den inn her: `Python Tutor `_. Eksempel 1 .......... Funksjoner gjør at man kan kjøre samme blokk med kode flere ganger, uten å måtte skrive den samme koden flere ganger. Her er et eksempel på kode hvor vi bruker funksjoner. I koden ser du at vi ikke nødvendigvis må kalle funksjonene i samme rekkefølge som de er definert. Eksempelet bruker også "docstrings" (documentation strings). Dette er teksten som står inne i trippel-quotes ``"""`` helt i begynnelsen av en funksjon. Docstrings forklarer hva funksjonen gjør og kan brukes av andre programmer. Prøv for eksempel å muse over funksjonsnavnene i VScode. Last ned filen her: :download:`eksempel_1.py`. .. literalinclude:: eksempel_1.py Noen steder i koden er det brukt en ekstra ``\``. Se for eksempel på ``ascii_castle()``. Her står det ``\'`` noen steder, men når vi kjører programmet printes ikke ``\``. Dette er fordi ``\`` er en så kalt 'escape character'. Vi kan bruke ``\`` før tegn som ellers ville ha noen annen betydning i en streng. For eksempel, om vi ikke hadde brukt ``\`` før ``'`` ville Python trodd at strengen var slutt ved ``'`` og vi hadde fått en feilmelding (prøv gjerne). Men når vi putter ``\`` før ``'`` sier vi til Python at vi ikke mener at strengen er slutt her, uten at Python skal printe tegnet ``'``. Siden ``\`` er et spesielt tegn på denne måten må vi bruke ``\`` før ``\`` om vi vil at Python skal lese strengen som tegnet ``\`` og ikke som en escape character. Det er derfor det står ``\\`` på alle steder hvor vi vil printe ``\``. Du kan lese mer om escape characters `her `_, og `her `_ er en liste med eksempler på alle escape characters i Python 3. Kjør koden. Hvorfor blir ikke ``ascii_square()`` skrevet ut? Eksempel 2 .......... Funksjoner kan også brukes til å regne ut en verdi vi vil bruke seinere. Da bruker vi ``return`` i slutten av funksjonen og sier at den "returnerer" en verdi. Hva om vi vil lagre resultatet i en variabel? For eksempel, hvis vi vil huske navnet fra tidligere funksjon ``hello`` kan vi lagre resultatet i ``myName``. I eksempelet er det to funksjoner: ``hello1`` og ``hello2``. ``hello1`` bruker print() mens ``hello2`` bruker return i slutten av funskjonen. Last ned filen her: :download:`eksempel_2.py`. .. literalinclude:: eksempel_2.py Kjør koden. Hva er forskjellen på ``hello1`` og ``hello2``? Hva lagres i ``myName``? Eksempel 3 .......... I dette eksemplet bruker vi f-string, f-string er en formateringsteknikk for strenger i Python. Du bruker den ved å plassere en f, eller F, foran ønsket anførselstegn ('..' eller ".."). Det fine med f-string er at du kan legge til variabler og uttrykk direkte i teksten ved å omringe de med krøllete parenteser { }. Last ned filen her: :download:`eksempel_3.py`. .. literalinclude:: eksempel_3.py Eksempel 4 .......... I dette eksempelet skal vi bruke flere funksjoner sammen for å bestille kaffe og kjeks. Først den samme som tidligere for å si hallo, og så en ny funksjon for å bestille mat. Legg merke til at ``make_order`` kaller ``order`` to ganger med forskjellige argumenter, og bruker begge resultatene. Last ned filen her: :download:`eksempel_4.py`. .. literalinclude:: eksempel_4.py Hvordan bruker vi disse tre funksjoner sammen? Diskuter med en andre personer hvordan resultaten fra den første og andre funskjonene brukes i den tredje funskjonen. Her er et annet eksempel på å bruke to funksjoner sammen :download:`eksempel_4b.py`. .. literalinclude:: eksempel_4b.py Hvordan brukes den første funskjonen i den andre funskjonen? Se på hvordan brukes vi int og str sammen i begge. Eksempel 5 .......... Funksjoner kan også brukes for å gjøre matematiske beregninger. Mange ganger vil man gjøre samme beregning flere ganger. Da er det lurt å plassere koden for beregningen i en funksjon som man siden kan kalle flere ganger. Om man vil gjøre flere ulike beregninger etterpå hverandre kan man dessuten gjøre det. Her er et eksempel på kode hvor vi bruker funksjoner for å regne ut lengden til hypotenusen i en rettvinklet trekant og gjennomsnittet av tre tall. Last ned filen her: :download:`eksempel_5.py`. .. literalinclude:: eksempel_5.py Kjør koden. Ble outputen hva du hadde ventet deg? Kan du lage noen funksjoner til, for å unngå repetisjonen i print-linjene? Eksempel 6 .......... I dette eksempelet bruker vi en funksjon for en beregning og en funksjon for å lage en streng. Vi beregner og printer andregradspolynomer. Last ned filen her: :download:`eksempel_6.py`. .. literalinclude:: eksempel_6.py I koden har vi brukt en f-string for å lage en streng. Du trenger ikke å bruke f-strings akkurat nå, men nå vet du at de finnes. Du kan finne en kort introduksjon til f-strings `her `_ om du vil vite mer. Her brukes ``return`` i ``poly_string()``, i stedet for å printe direkte i funksjonen. Prøv å endre i koden så at ``poly_string()`` printer strengen, i stedet for å bruke ``return``. Hva skjer? Eksempel 7 .......... Det er mulig å definere en funksjon i Python uten å bruke ``return``. Da returnerer Python verdien ``None`` i bakgrunnen. Husk at om du vil gi verdien fra en funksjon til en annen funksjon må du bruke ``return``. Her er noen eksempler på hva som skjer om man ikke bruker ``return`` i funksjoner. Last ned filen her: :download:`error_1.py`. .. literalinclude:: error_1.py Når du prøver å kjøre koden får du en feilmelding. - Se på det vanlige outputet før feilmeldingen: hvorfor ser det slik ut? - Hvorfor får du error når du kjører koden? - Hvorfor blir ikke den siste raden skrevet ut? - Endre koden slik at den kjører. - Hvorfor fikk du ingen feilmelding fra ``den_er_feil()``-funksjonen? Oppgaver -------- I disse oppgavene skal du lage og bruke funksjoner. Oppgave 1 ......... I denne oppgaven skal vi fylle inn funksjonene for å finne (den innvendige) tangeringssirkelen til en trekant. `Tangeringssirkelen `_ er den største sirkelen som får plass inne i en trekant. .. image:: ./incircle.png :width: 300 Her er det ganske mange ting vi må regne ut, men ved å bryte problemet ned til mindre funksjoner og sette dem sammen blir det enklere å løse. Start med å laste ned :download:`oppgave_1.py`. Det første vi ser er:: def side_length(x1, y1, x2, y2): """Returns the length of the side between the points (x1,y1) and (x2,y2)""" # Skriv kode her pass Bytt ut kommentaren ``# Skriv kode her`` med kode som regner ut avstanden mellom (x1,y1) og (x2,y2). Tips: du kan bruke ``sqrt`` til å regne ut kvadratrot. Den neste funksjonen er ``mid``. Her skal vi finne midten av trekanten, ett koordinat av gangen. Formelen (fra `wikipedia `_) er: .. math:: \frac{(pointA \cdot a) + (pointB \cdot b) + (pointC \cdot c)}{a+b+c}. **NB**: Vi regner ut senteret for x- og y-koordinatet separat. `pointA` er bare ett tall. Funksjonen ``incircle_radius`` skal regne ut radiusen til tangenssirkelen basert på sidelengdene `a`, `b` og `c`. Igjen finner vi formelen på `wikipedia `_ .. math:: r = \sqrt{\frac{(s-a)(s-b)(s-c)}{s}} Der :math:`s=(a+b+c)/2`. Til slutt skal vi fylle inn ``find_incircle``. Alle stedene det står ``0`` skal vi bruke funksjonene vi allerede har skrevet til å regne ut den riktige verdien. Her gjelder det å holde tunga rett i munnen og bruke de riktige punktene og sidelengdene. Når du er ferdig, prøv å kjøre programmet og test noen forskjellige trekanter! Oppgave 2 ......... I denne oppgaven skal vi lage våre egne funksjoner som beregner maximum og minimum av to tall. Siden skal vi sammenligne disse med Pythons innebygde funksjoner ``max()`` og ``min()``. I filen ``oppgave_2.py``, skriv kode som gjør følgende: 1. Definerer en funksjon som heter ``egen_max()`` som beregner maximum av heltallene :math:`a` og :math:`b`. Det går ann å beregne uten ``if`` med denne formelen: .. math:: \frac{a + b + | a - b |}{2}. (:math:`|a - b|` betyr absoluttverdien av :math:`a-b`) **Funksjonen skal returnere et heltall.** 2. Definerer en funksjon som heter ``egen_min()`` som beregner minimum av heltallene :math:`a` og :math:`b` ifølge formelen: .. math:: \frac{a + b - | a - b |}{2}. **Funksjonen skal returnere et heltall.** 3. Spør brukeren om to tall og skriver siden ut resultatet av ``egen_max()``, ``max()``, ``egen_min()`` og ``min()`` på tallene. La det være en tom linje etter inputen, og mellom resultatet for maximum og minimum. Eksempelkjøring:: Tall 1: 39 Tall 2: 14 egen_max(39, 14) = 39 max(39, 14) = 39 egen_min(39, 14) = 14 min(39, 14) = 14 Prøv å kjøre din kode med noen ulike tall. Gir dine egne funksjoner riktig svar? Tips **** Du kan bruke Pythons innebygde funksjon ``abs()`` til å beregne absoluttverdi. Du finner informasjon om hvordan funksjonen fungerer `i Pythons dokumentasjon `_. Oppgave 3 ......... I denne oppgave skal vi fortsette med konverteringen mellom Fahrenheit og Celsius vi begynte med forrige uke. Men denne gangen skal vi plassere beregningen i en funksjon. I filen ``oppgave_3.py``, skriv kode som gjør følgende: 1. Definerer en funksjon som heter ``fahrenheit_til_celsius()`` som tar en temperatur i enheten Fahrenheit og returnerer en temperatur i enheten Celsius. Den matematiske formelen er: .. math:: T_C = (T_F - 32) \cdot \frac{5}{9}, hvor :math:`T_C` er temperaturen i Celsius og :math:`T_F` er temperaturen i Fahrenheit. 2. Definerer en funksjon som heter ``celsius_til_fahrenheit()`` som tar en temperatur i enheten Celsius og returnerer en temperatur i enheten Fahrenheit. Den matematiske formelen er: .. math:: T_F = \frac{9}{5} \cdot T_C + 32, hvor :math:`T_C` er temperaturen i Celsius og :math:`T_F` er temperaturen i Fahrenheit. 3. Spør brukeren om en temperatur i enheten Fahrenheit og bruker ``fahrenheit_til_celsius()`` til å beregne tilsvarende temperatur i enheten Celsius. Denne temperaturen skrives ut på skjermen med **én** desimal. 4. Tar verdien du fikk i steg 3 og bruker ``celsius_til_fahrenheit()`` til å beregner tilsvarende temperatur i enheten Fahrenheit. Denne temperaturen skrives ut på skjermen med **èn** desimal. Eksempelkjøring:: Gi en temperatur i Fahrenheit: 225 Temperatur i Celsius: 107.2 Temperatur i Fahrenheit: 225.0 Hva skjer om du avrunder resultatet til èn desimal inne i funksjonene, så at ``fahrenheit_til_celsius()`` og ``celsius_til_fahrenheit()`` begge returnerer tall med kun èn desimal? Prøv dette med 44 og 67 Fahrenheit som input. Hvorfor blir resultatet slik? Tips **** Bruk den innebygde funksjonen ``round()`` til å bestemme antall desimaler. Du finner informasjon om hvordan funksjonen fungerer `i Pythons dokumentasjon `_. Oppgave 4 ......... I denne oppgaven skal vi fortsette med tekstboksen vi holdt på med forrige uke. Denne gangen skal vi plassere tegningen av boksen i en funksjon. I filen ``oppgave_4.py``, skriv kode som gjør følgende: 1. Definerer en funksjon (som du selv velger et deskriptivt navn for) som tar en streng som argument og tegner en boks runt teksten på skjermen. Det skal være **ett** mellomrom før og etter strengen, og **en** ``=`` på hver side. Fyll inn over og under tilsvarende. 2. Spør brukeren om navn. 3. Bruker funksjonen du definerte i 1) til å tegne en boks rund navnet på skjermen. La det være en tom linje før og etter boksen. 4. Ønsker brukeren en god dag (velg setning selv). Eksempelkjøring:: Hva heter du? Lina ======== = Lina = ======== Jeg håper du får en fin dag!