10: Functies

In deze les laten we je het belangrijkste idee van programmeren zien: je eigen functies definiëren! Functies zorgen ervoor dat je programma korter wordt, beter gestructureerd, en in onderdelen herbruikbaar. In latere lessen zullen we andere voordelen zien zoals recursie.

Een functie definiëren

We beginnen met een voorbeeld. Ken je de functie abs nog? Ze neemt één argument (een getal x), en ze geeft als resultaat de absolute waarde van x terug (m.a.w. x wanneer x ≥ 0, en -x wanneer x < 0). Kijk hoe we deze functie in Python definiëren:

def abs(x):     # definieer een functie met als naam 'abs' die één parameter heeft namelijk 'x'
  if x >= 0:    # het lichaam van de functie start hier
    return x
  else:
    return -x   # het lichaam van de functie stopt hier
(Klik hier om deze code in de console te testen.)

De twee delen van een functiedefinitie

In de eerste regel van een functiedefinitie staan de naam van de functie en haar parameters. De regel is van de vorm

def «functie-naam»(«parameterlijst»):

In het voorbeeld hierboven is abs de naam van de functie en bestaat de parameterlijst uit één element, namelijk x. Het wordt een parameterlijst genoemd omdat het meerdere parameters kunnen zijn, zoals  x, y, z; het is ook mogelijk om 0 parameters te hebben, met andere woorden een lege lijst. Bij een oproep van een functie moet je precies zoveel argumenten opgeven als de functie parameters heeft, dus voor elke parameter van de functie één argument. Bij een oproep abs(5) van de hierboven gedefinieerde functie abs zeggen we dan ook dat 5 het argument is voor de parameter x.

Alles na de eerste regel van de definitie van een functie is het lichaam van de functie. Het lichaam is een ingesprongen blok met opdrachten. Wanneer de functie wordt aangeroepen, wordt het lichaam uitgevoerd, waarbij elke parameter de waarde krijgt van het overeenkomstige argument van de functie-oproep. Wanneer we tenslotte de volgende regel in het lichaam van de functie bereiken:

return «waarde»

stopt de functie en geeft «waarde» als resultaatwaarde terug. Zoals het abs-voorbeeld laat zien kan het lichaam meerdere return-opdrachten bevatten; alleen de eerste heeft echter effect omdat daarna de functie stopt.

Voorbeeld: Definitie en aanroep van een functie

Het volgende programma bevat een definitie van een functie en enkele andere opdrachten die worden uitgevoerd nadat de functie is gedefinieerd.

Voorbeeld
Kwadraat-functie

We zien dat de naam van de functie square is, met slechts één parameter x, en dat het lichaam van de functie bestaat uit één regel: return x*x. Verder, buiten de functie, zijn er twee opdrachten die de functie in totaal drie keer aanroepen.

  1. Wanneer de eerste opdracht wordt uitgevoerd, moet Python square(10) evalueren.
    • Python vergelijkt de argumentenlijst (10) met de parameterlijst (x). Het voert het lichaam van de functie uit, nl.: return x*x, waarbij het zich herinnert dat x gelijk is aan 10. Dus geeft x*x het resultaat 100 en dat wordt afgedrukt.
  2. Wanneer de tweede opdracht wordt uitgevoerd, moet Python square(square(2)) evalueren.
    • Het binnenste deel square(2) wordt eerst uitgevoerd. We nemen voor x het getal 2 en voeren het lichaam van de functie uit. Dat geeft als resultaat 4.
    • Dan wordt de buitenste uitdrukking uitgevoerd, en omdat square(2) het getal 4 heeft teruggegeven, roepen we nu square(4) aan. Dit levert 16 als resultaatwaarde, en dat wordt afgedrukt.

Zoals gebruikelijk kun je het programma uitproberen in Python3 Visualizer.

Vier vaak voorkomende fouten

Een vaak voorkomende fout die je kunt maken bij de definitie van een functie is het vergeten van de return-opdracht.

Voorbeeld
Fout 1: return vergeten

Zoals je kunt zien: wanneer geen return-opdracht in het lichaam voorkomt, geeft de functie None als resultaat. Dus, wanneer je bij een oefening niet het gewenste resultaat krijgt omdat de functie None teruggeeft dan is het probleem vaak dat er bij de uitvoering van de functie geen return-opdracht uitgevoerd is.

Je kunt ook de return-opdracht met reden weglaten. Dit is zinvol als je functie een neveneffect heeft anders dan het geven van een resultaatwaarde:
Voorbeeld: Een neveneffect en geen return-opdracht

Een andere veelvoorkomende fout is vergeten om in te springen, hetgeen resulteert in IndentationError.

Voorbeeld
Fout 2: vergeten om in te springen

Zoals we in les 2 zagen, veroorzaakt het aanroepen van een functie met te weinig of te veel argumenten een fout.

Voorbeeld
Fout 3: aanroep met te veel argumenten

Tenslotte, wanneer je een tikfout maakt bij de aanroep van een functie, krijg je een foutmelding waarbij gemeld wordt dat de functie niet gedefinieerd is.

Voorbeeld
Fout 4: verkeerde naam

Probeer het zelf

Programmeeroefening: Tot de derde macht
Definieer een functie derdeMacht(n), die één getal n als argument neemt, en n × n × n als resultaat teruggeeft.
Voer testcommando's zoals print(myfunction("test argument")) hieronder in.

Twee of meer argumenten

De functies hierboven hebben slechts één argument, maar een functie kan een willekeurig aantal argumenten accepteren. Je hebt bijvoorbeeld al input() met 0 argumenten aangeroepen (en je zult een functie definiëren met 0 argumenten in les 15A).

Hier is een voorbeeld van een functie uit de meetkunde met twee argumenten. Neem aan dat we een functie nodig hebben om de oppervlakte van een driehoek uit te rekenen, waarbij de lengte van de basis en de bijbehorende hoogte zijn gegeven. De formule voor de oppervlakte is

oppervlakte = basis × hoogte / 2

Dan kunnen we in Python een functie driehoekOpp als volgt definiëren:

Voorbeeld
Een functie met twee argumenten

Zoals je kunt zien, is de enige verandering dat we def «functienaam»(«argument1») veranderen in def «functienaam»(«argument1», «argument2»).

In de laatste oefening vragen we je om een functie met twee argumenten te schrijven, waarmee je de omtrek van een rechthoek kunt berekenen (de omtrek is de totale lengte van alle zijden). Bij een rechthoek met een gegeven breedte en hoogte, wordt de omtrek gegeven door de volgende formule:

omtrek = breedte + hoogte + breedte + hoogte

Programmeeroefening: Rechthoek
Definieer een functie omtrek(breedte, hoogte), die de omtrek van een rechthoek berekent.
Voer testcommando's zoals print(myfunction("test argument")) hieronder in.

Functies die functies aanroepen

Functies zijn de bouwstenen van goed geschreven grote programma's: je kunt dezelfde taak twee keer uitvoeren zonder dezelfde code twee keer te schrijven, en je kunt oplossingen van veelvoorkomende taken opnieuw gebruiken. Hier is een voorbeeld van het schrijven van een functie die gebruikt wordt in een andere functie.

Voorbeeld
Kun je voorspellen wat deze functie doet voordat je het programma uitvoert?
Herinner je uit les 4 dat de vermenigvuldiging van strings met een geheel getal  inhoudt dat de string dit aantal keren herhaald wordt. Zo is bijvoorbeeld "tar"*2 gelijk aan "tartar".

Je bent nu klaar voor de volgende les!