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 sirkelregnerog deretter brukesirkelregner.Sirkel().Vi kan bruke
import sirkelregner as srog deretter brukesr.Sirkel().Vi kan bruke
from sirkelregner import Sirkelog 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.