Dokumentasjon#
God, gjenbrukbar kode bør ha god dokumentasjon. Å skrive dokumentasjon gjør at andre kan bruke koden vår uten å måtte lese hele kildekoden.
Type hints#
I funksjoner og metoder trenger vi ikke å definere hvilken type data vi forventer som argument, og heller ikke hvilken type data som funksjonen returnerer. Det er vi nødt til i andre språk som Java. La oss se på et eksempel.
class Elev:
def __init__(self, navn):
self.navn = navn
def hils(self, kompis_navn):
return f"{self.navn} hilser på {kompis_navn}"
elev = Elev("Linnea")
print(elev.hils("Beate"))
Linnea hilser på Beate
hils()
-metoden skal ta en string kompis_navn
og returnere en string f{self.navn} hilser på {kompis_navn}
, men det er ingenting som hindrer oss i å skrive inn feil datatyper og det er heller ingenting som sier oss at metoden skal returnere en string, med mindre vi leser koden.
For å signalisere hvilke datatyper vi forventer som argument, og hvilke datatyper som returneres, kan vi bruke type hints.
class Elev:
def __init__(self, navn):
self.navn = navn
def hils(self, kompis_navn : str) -> str:
return f"{self.navn} hilser på {kompis_navn}"
Der det står kompis_navn : str
mener vi altså at variabelen med navn kompis_navn
burde være en str
. Pilen -> str
betyr at funksjonen skal returnere en str
. Dette sier til brukeren hva som returneres og hva som skal puttes inn som argument. Dette vises for eksempel i VSCode og dokumentasjonen vi lager senere.
Lage og bruke programmer i andre programmer#
Det er enkelt å lage og bruke programmer i andre programmer. Vi lager først en Python-fil som definerer funksjoner og klasser, og deretter bruker vi import
for å hente inn klassene og funksjonene til et annet program.
La oss lage et program som regner på sirkler.
# sirkelregner.py
import math
class Sirkel:
# Konstruktøren
def __init__(self, r : float):
self.r = r
self.areal = math.pi * self.r ** 2
self.omkrets = 2 * math.pi * self.r
# Skalerer sirkelen med en faktor k
def skaler(self, k : float):
self.__init__(self.r * k)
# Returnerer en string når man printer objekter av klassen
def __str__(self) -> str:
return f"Sirkel med radius: {self.r}, areal: {round(self.areal, 2)} og omkrets: {round(self.omkrets, 2)}"
Hvis vi lagrer koden over som sirkelregner.py
kan vi enkelt bruke import
for å hente innholdet til et annet program. Dette kan vi gjøre på noen forskjellige måter:
Vi kan bruke
import sirkelregner
og deretter brukesirkelregner.Sirkel()
.Vi kan bruke
import sirkelregner as sr
og deretter brukesr.Sirkel()
.Vi kan bruke
from sirkelregner import Sirkel
og deretter brukeSirkel()
.
Siden pakken bare inneholder én klasse velger jeg å bruke siste alternativ.
from sirkelregner import Sirkel
sirkel = Sirkel(1) # Lager et Sirkel-objekt
print(sirkel) # Skriver ut Sirkel-objektet
sirkel.skaler(2) # Skalerer Sirkel-objektet med faktor 2
print(sirkel) # Skriver ut Sirkel-objektet
Sirkel med radius: 1.000, areal: 3.142 og omkrets: 6.283
Sirkel med radius: 2.000, areal: 12.566 og omkrets: 12.566
Som vi ser kan vi enkelt importere Sirkel
-klassen og bruke den i et annet program. Det avhenger så klart av at vi vet hvordan vi skal bruke sirkelregner
. Hvis vi skal formidle hvordan en pakke fungerer, må vi skrive en god dokumentasjon.
Dokumentasjon med docstrings#
Vi kan enkelt skrive dokumentasjonen inn i koden ved å bruke """
-kommentarer. Dette er en standard som er støttet av Python. Akkurat hvordan man formaterer setningene i kommentarene er det flere ulike konvensjoner for. I dette eksempelet vil vi bruke konvensjonen Google Docstrings.
Her kommer et eksempel av sirkelregner.py
skrevet med docstrings. Legg merke til hvordan man kan spesifisere attributter, args (argumenter) og return-verdier.
"""Dette programmet gir en klasse som gjør at man kan lage et skalerbart sirkelobjekt.
Typisk eksempel på bruk:
sirkel = Sirkel(1)
print(sirkel)
sirkel.skaler(2)
print(sirkel)
"""
import math
class Sirkel:
"""En klasse som håndterer sirkelobjekter
Attributes:
r: en radius som et tall.
areal: arealet regnet fra radius
omkrets: omkretsen regnet fra radius
"""
# Konstruktøren
def __init__(self, r : float):
"""Initialiserer et sirkelobjekt med en radius r.
Args:
r: en radius som et tall
"""
self.r = r
self.areal = math.pi * self.r ** 2
self.omkrets = 2 * math.pi * self.r
# Skalerer sirkelen med en faktor k
def skaler(self, k : float):
"""Skalerer sirkelobjektet med en faktor k.
Args:
k: en faktor (tall) som skal ganges med radius.
"""
self.__init__(self.r * k)
# Returnerer en string når man printer objekter av klassen
def __str__(self) -> str:
"""Gir en string når man printer sirkelobjekter.
Returns:
En string som inneholder radius, areal og omkrets av sirkelen.
"""
return f"Sirkel med radius: {self.r}, areal: {round(self.areal, 2)} og omkrets: {round(self.omkrets, 2)}"
Vi kan nå enkelt hente hele dokumentasjonen til dette programmet ved å bruke help()
-funksjonen i Python.
import sirkelregner
help(sirkelregner) # Gir hele dokumentasjonen
help(sirkelregner.Sirkel) # Gir dokumentasjonen for Sirkel-klassen
help(sirkelregner.Sirkel.skaler) # Gir dokumentasjonen for skaler()-metoden
Generere dokumentasjon med pydoc
#
Python-installasjoner kommer med pakken pydoc
som lar oss skrive dokumentasjonen fra docstrings over til en .html
-fil som kan åpnes i nettleseren. Dette gjør vi ved å sørge for at terminalvinduet er åpnet i mappen som man har pakken og skrive
python -m pydoc -w sirkelregner
Erstatt sirkelregner
med din pakkes navn. Da vil du få en .html
-fil med litt retro stil, men som forklarer metoder og objekter i programmet ditt, og som kan sendes videre til brukeren.