3.2. Aandachtspunten bij het schrijven van functies#

3.2.1. Docstrings#

In de vorige sessie hebben we al gezien dat het belangrijk is om commentaar toe te voegen aan je scripts. Dit bevordert de leesbaarheid van je code en zorgt ervoor dat je ook na een lange tijd toch weer snel kan zien wat jouw code doet en waarvoor je deze geschreven hebt.

Bij functies voegen we vaak nog een speciaal soort commentaar toe: de docstring. Dit is een gestandaardiseerde manier om te beschrijven wat een functie doet en wat deze als in- en output gebruikt. Zo kan je snel zien wat het nut van een functie is en wat je ermee kan doen.

De docstring bevindt zich meteen onder de functie definitie en begint en eindigt met drie aanhalingstekens (''' of """). Verder bevat een goede docstring de volgende elementen:

  • Op de eerste regel van de docstring, recht achter de eerste drie aanhalingstekens, zetten we een korte beschrijving van de functie;

  • Vervolgens geven we aan wat voor inputs en outputs de functie heeft, met achter de naam van de variabele een korte omschrijving.

  • Vaak is het ook handig om daarbij aan te geven wat het type van deze in- en outputs is. De laatste regel van de docstring bevat alleen de drie afsluitende aanhalingstekens.

import math

def pythagoras_c(a, b):
    ''' bereken de lengte van de schuine zijde
    inputs:
      a (float) - de lengte van een korte zijde
      b (float) - de lengte van de andere korte zijde
    outputs
      c (float) - de lengte van de schuine zijde
    '''
    c = math.sqrt( (a ** 2) + (b ** 2) )

    return c

print('De schuine zijde van een rechthoekige driehoek met zijden 3 en 4 is:')
print(pythagoras_c(3, 4))
De schuine zijde van een rechthoekige driehoek met zijden 3 en 4 is:
5.0

Zoals je in het voorbeeld ziet lijkt het soms wat veel werk om voor elke functie een docstring te schrijven, zeker als deze langer wordt dan de eigenlijke functie. Toch zal je merken dat je uiteindelijk, als je na een tijd terugkijkt naar je code, een code met docstrings veel sneller weer begrijpt dan eentje zonder.

3.2.2. Variabele types voor de in- en output#

Elk soort Python variabele kan gebruikt worden als in- of output van je functie, en deze kunnen zelfs gecombineerd worden. Het is dus bijvoorbeeld mogelijk om een functie te schrijven die een int en een str als input accepteert een een float teruggeeft als output. Python vindt dit geen probleem en, wanneer je zo’n soort functie nodig hebt is het ook heel fijn en makkelijk dat dit kan.

def voorbeeld_functie(getal, tekst):
  ''' deel het getal door de lengte van de tekst
  inputs:
    getal (int)
    tekst (str)
  outputs:
    resultaat (float)
  '''
  resultaat = getal / len(tekst)

  return resultaat

Wat echter ook mogelijk is, maar een stuk minder wenselijk, is dat de functie soms het ene type als input accepteert, maar soms ook een ander type en dat het ook nog kan wisselen in wat voor output het geeft. Dit zorgt vaak voor problemen verderop in je code wanneer het type van een object ineens anders blijkt te zijn dan je verwacht.

Python controleert niet voor jou wat voor type de input en output variabelen van je functies zijn. Deze flexibiliteit is een van de grote voordelen van Python, maar zorgt er in dit geval voor dat jij zelf er goed op moet letten dat je hier netjes mee om gaat. Geef dus altijd netjes in de docstring aan wat voor type inputs en outputs de functie verwacht en schrijf je code dan ook zo dat er alleen deze types gebruikt en teruggegeven kunnen worden.

Een voorbeeld van een functie die het niet zo nauw neemt met het type outputargument staat hieronder. In de laatste regel tellen we de resultaten bij elkaar op, wat geen probleem geeft als we telkens een getal terug kregen van onze functie. In het laatste geval krijgen we echter een str terug, en zorgt dit voor een (misschien niet zo eenvoudig op te lossen) foutmelding.

def voorbeeld_functie(getal, tekst):
    ''' deel het getal door de lengte van de tekst
    inputs:
      tekst (str)
      getal (int)
    outputs:
      resultaat (float / str)
    '''

    if len(tekst) > 0:
        resultaat = getal / len(tekst)
        return resultaat
    else:
        return 'Getal is kleiner of gelijk aan 0!'


res_1 = voorbeeld_functie(3, 'abc')
res_2 = voorbeeld_functie(3, 'a')
res_3 = voorbeeld_functie(3, '')

print(res_1 + res_2 + res_3)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-d6687de1b4ae> in <cell line: 21>()
     19 res_3 = voorbeeld_functie(3, '')
     20 
---> 21 print(res_1 + res_2 + res_3)

TypeError: unsupported operand type(s) for +: 'float' and 'str'