Du har en funksjon som legger sammen to tall. Fungerer fint. Men hva når du trenger å legge sammen tre? Eller ti? Du kan ikke lage en ny funksjon for hvert antall. Med *args og **kwargs i Python slipper du å bestemme antall parametere på forhånd. Funksjonen tar imot så mange verdier du sender inn.
Slik fungerer *args i Python
Stjerna foran parameternavnet gjør at Python samler alle posisjonsargumenter i en tuple:
def summer(*tall):
resultat = 0
for t in tall:
resultat += t
return resultat
print(summer(1, 2, 3)) # 6
print(summer(5, 10, 15, 20, 25)) # 75
Navnet "args" er bare en konvensjon. Skriv gjerne *tall, *verdier, eller hva som helst. Det er stjerna som gir funksjonaliteten. Python pakker alle verdiene du sender inn i en tuple, og du kan iterere over den med en for-løkke, akkurat som over en vanlig liste.
Sender du ingen argumenter, blir tupelen tom. Funksjonen krasjer ikke, men du får 0 tilbake fra eksempelet over. Det er god oppførsel.
Forskjellen fra en liste som parameter
Et alternativ er å sende inn en liste:
def summer_liste(tall_liste):
return sum(tall_liste)
summer_liste([1, 2, 3]) # Må pakke inn i en liste
Med *args slipper du hakeparentesene:
summer(1, 2, 3) # Sender tallene direkte
Forskjellen er brukervennlighet. *args gir et renere kall, spesielt når du ikke allerede har verdiene i en liste. Har du en eksisterende liste, kan du pakke den ut med stjerne: summer(*min_liste).
Slik fungerer **kwargs
Dobbel stjerne samler nøkkelordargumenter i en dictionary:
def vis_info(**info):
for nokkel, verdi in info.items():
print(f"{nokkel}: {verdi}")
vis_info(navn="Anna", alder=30, by="Oslo")
Resultatet blir:
navn: Anna
alder: 30
by: Oslo
Igjen er "kwargs" bare en konvensjon. Du kan kalle parameteren **data eller **innstillinger. Det er dobbelt-stjerna som gjør at Python samler nøkkelord-verdi-parene i en dictionary.
**kwargs er spesielt nyttig når du bygger funksjoner som tar imot innstillinger. I stedet for å definere ti valgfrie parametere med standardverdier, lar du brukeren sende inn kun det de trenger. Alt annet ignoreres eller får en standard.
Kombiner vanlige parametere med *args og **kwargs
Alle tre typene kan kombineres, men rekkefølgen er fast:
def bestilling(kunde, *produkter, **detaljer):
print(f"Kunde: {kunde}")
print(f"Produkter: {produkter}")
print(f"Detaljer: {detaljer}")
bestilling("Erik", "Laptop", "Mus", frakt="Express", rabatt=10)
Resultatet:
Kunde: Erik
Produkter: ('Laptop', 'Mus')
Detaljer: {'frakt': 'Express', 'rabatt': 10}
Rekkefølgen er alltid: vanlige parametere, deretter *args, deretter **kwargs. Bytter du om, gir Python en SyntaxError. Denne rekkefølgen er logisk: først de obligatoriske verdiene, så de ekstra posisjonelle, og til slutt de navngitte tilleggsverdiene.
Pakk ut med stjerner
Utpakking med * og ** fungerer også den andre veien. Har du en liste eller dictionary, kan du pakke dem ut som argumenter til en funksjon:
def hils(fornavn, etternavn, alder):
print(f"Hei, {fornavn} {etternavn}. Du er {alder} år.")
person = {"fornavn": "Kari", "etternavn": "Hansen", "alder": 28}
hils(**person) # Hei, Kari Hansen. Du er 28 år.
Nøklene i dictionaryen må matche parameternavnene i funksjonen. Mangler en nøkkel, får du en TypeError. Har du en ekstra nøkkel som ikke matcher, får du også en TypeError. Det gir deg trygghet: Python sjekker at alt stemmer.
For lister bruker du én stjerne:
tall = [10, 20, 30]
print(*tall) # 10 20 30 (tre separate argumenter)
Praktisk bruk av args og kwargs
Den vanligste bruken er i dekoratorer og wrapper-funksjoner, der du ikke vet hvilke argumenter den indre funksjonen tar:
def logg_kall(funksjon):
def wrapper(*args, **kwargs):
print(f"Kaller {funksjon.__name__}")
return funksjon(*args, **kwargs)
return wrapper
Wrapper-funksjonen videreformidler alle argumenter til den opprinnelige funksjonen uten å vite hva de er. Denne teknikken brukes i de fleste Python-rammeverk. Du trenger ikke forstå dekoratorer i detalj ennå, men det er nyttig å gjenkjenne mønsteret når du ser det i andres kode.
En annen vanlig bruk er funksjoner som bygger konfigurasjoner. Du sender inn kun de feltene du vil overstyre, og resten beholder standardverdier:
def opprett_bruker(navn, **ekstra):
bruker = {"navn": navn, "rolle": "bruker"}
bruker.update(ekstra)
return bruker
print(opprett_bruker("Anna", rolle="admin", avdeling="IT"))
Tre feil å unngå med args og kwargs
Feil rekkefølge i parameterlisten. Skriver du def f(**kwargs, *args), får du en SyntaxError. *args må alltid komme før **kwargs.
Bruker *args når du trenger navngitte verdier. Hvis rekkefølgen på verdiene betyr noe (som bredde og høyde), er vanlige parametere tryggere enn *args. Navngitte parametere dokumenterer seg selv.
Fanger alt med **kwargs uten validering. Når du aksepterer hva som helst, risikerer du skrivefeil i nøkkelnavnene som aldri blir oppdaget. Legg inn sjekker for forventede nøkler når det er viktig.
En enkel validering kan se slik ut:
def innstillinger(**kwargs):
gyldige = {"farge", "storrelse", "skrift"}
for nokkel in kwargs:
if nokkel not in gyldige:
raise TypeError(f"Ukjent innstilling: {nokkel}")
Med denne sjekken oppdager du skrivefeil umiddelbart i stedet for å lure på hvorfor innstillingen ikke tok effekt.
Neste steg
Nå som du kan bruke *args og **kwargs i Python, har du full fleksibilitet i funksjonsdesign. Vil du skrive korte, anonyme funksjoner, viser lambda-funksjoner deg hvordan. Trenger du å håndtere feil i funksjonene dine, er try og except det riktige verktøyet. Du finner også flere eksempler på avansert funksjonsbruk i Python-dokumentasjonen.
Denne videoen er hentet fra kurset Python for nybegynnere på Utdannet.no. I det fulle kurset lærer du også datastrukturer, objektorientert programmering og hvordan du strukturerer større prosjekter.




