Uit noodzaak om al aan de slag te kunnen, hebben we enkele basisfuncties ontmoet, zoals print()
, input()
en type()
. In dit hoofdstuk worden deze en meer functies in meer detail besproken. Pas later zien we hoe je je eigen functies kunt maken.
In het algemeen beschrijven we een functie als een blok herbruikbare code dat een bepaalde actie uitvoert. Zoals we variabelen vergeleken met gemarkeerde dozen, maken we een analogie tussen een functie en een grote machine. Bijvoorbeeld, een machine die pannenkoeken bakt. Het zal je niet verbazen dat die de veelbelovende naam ‘pannenkoek machine’ krijgt. Er zijn input sleuven aan de bovenkant, met labels melk, eieren, en meel. Dat zijn de functie argumenten. Je kunt beïnvloeden wat voor pannenkoeken de machine bakt door de juiste ingrediënten in de inputs te stoppen; bijvoorbeeld, als je volkoren pannenkoeken wilt, doe je volkoren meel in de meel input. Natuurlijk kunnen de zaken dramatisch fout lopen als je eieren in de melk input doet. Volgorde en structuur zijn uitermate belangrijk! Als de inputs gevuld zijn, begint de machine te ratelen. Je wacht geduldig naast de output sleuf die (tot niemand’s verrassing) het label return draagt. Na enige tijd verschijnt er een pannenkoek in de uitvoer. Die pannenkoek is de retourwaarde die de machine heeft geproduceerd. Eén van de aardige dingen van de pannenkoek machine is dat - zelfs als jij niet weet hoe je een pannenkoek moet bakken - je toch pannenkoeken kunt krijgen als je maar de juiste ingrediënten verstrekt. Dat is ook aardig aan functies: ze kunnen complexe zaken voor je regelen, zonder dat je hoeft te weten hoe ze dat doen. Je hoeft eigenlijk slechts drie dingen te weten:
Iedere functie heeft een naam. Net als variabele namen, mogen functie namen alleen bestaan uit letters, cijfers en underscores, en mogen ze niet starten met een cijfer. Vrijwel alle standaard Python functies bestaan alleen uit kleine letters. Gewoonlijk is de naam van een functie een korte beschrijving van wat de functie doet. Horend bij de naam van de functie is er steeds een openings- en sluithaakje. Die zijn er altijd. Sterker nog, het paar haakjes maakt voor de programmeur net duidelijk het onderscheid tussen functies en variabelen.
Sommige functies worden aangeroepen met argumenten. Argumenten worden geplaatst tussen de haakjes die achter de functienaam staan. Als er meerdere argumenten zijn, worden die door komma’s gescheiden. Als er geen argumenten zijn, dan blijven de
haakjes leeg. De functie type()
eist exact één argument. De functie print()
laat een willekeurig aantal argumenten toe, telkens gescheiden met een komma. In het volgende voorbeeld worden drie argumenten gegeven, alledrie van het datatype string:
print( "Ik", "leer", "Python." )
Als een functie meerdere argumenten krijgt, is de volgorde cruciaal. Bijvoorbeeld, de standaard machtsfunctie pow()
krijgt twee argumenten, integers of floats, en rekent de waarde uit van de eerste die wordt verheven tot de macht weergegeven door de tweede. (Eerder zagen we al de ** operator waarmee we machten kunnen berekenen. Willen we bijvoorbeeld $2^3$ berekenen, dan kunnen we kiezen: 2**3
of pow(2,3)
.) Let op, de namen die aan de variabelen zijn gegeven doen niet ter zake, de eerste wordt verheven tot de macht die de tweede is. Volgende twee prints geven daarom een andere waarde (dit louter illustratief, de variabele namen van de tweede print houden geen steek):
basis = 2
exponent = 3
print( pow( basis, exponent ) ) # basis wordt tot exponent verheven (resultaat is 8)
print( pow( exponent, basis ) ) # exponent wordt tot basis verheven (verwarrend!) (resultaat is 9)
Een functie heeft vaak een retour waarde. Als een functie een waarde retourneert, kun je die in je code gebruiken. Bijvoorbeeld, de int()
functie retourneert een integer representatie van het argument dat is meegegeven. Je kunt deze retour waarde in een variabele stoppen middels een assignment, of je kunt de waarde op een andere manier gebruiken, bijvoorbeeld deze onmiddellijk printen. Je kunt er zelfs voor kiezen niks met de waarde te doen, maar in dat geval had het waarschijnlijk weinig zin om de functie aan te roepen. Voorspel even de uitvoer van volgende lijnen code:
x = 2.1
y = '3'
z = int( x )
print( z )
print( int( y ) )
Zoals je hierboven kunt zien, kun je zelfs een functie aanroep als argument meegeven aan een (andere) functie, bijvoorbeeld, in de laatste regel van de code hierboven krijgt de print()
functie als argument een aanroep van de int()
functie mee. De aanroep van int()
vindt dan plaats voordat de print()
wordt afgehandeld, dus de return waarde
van int()
is een argument voor print()
. We lezen hier dus van binnen naar buiten: y als argument voor int()
als argument voor print()
.
We bekijken in meer detail enkele ingebouwde functies in Python. Deze lijst is niet volledig. Wil je toch een volledige lijst? Dan vind je die terug op deze documentatie webpagina1.
int()
heeft één argument en retourneert een integer representatie van de waarde van het argument. Als de waarde een integer is, krijg je dezelfde waarde terug. Als de waarde een float is, krijg je een integer terug die de waarde van de float naar beneden heeft afgerond. Als het argument een string bevat die je als integer zou kunnen interpreteren, dan krijg je die integer terug als waarde. Anders krijg je een foutmelding. Bijvoorbeeld:
x = 2.1
y = '3'
z = 'Dit is een zin.'
print( int( x ) )
print( int( y ) )
print( int( z ) )
float()
heeft één argument en retourneert een floating-point representatie van de waarde van het argument. Als de waarde een integer is, krijg je dezelfde waarde terug als float. Als het argument een float is, krijg je dezelfde waarde terug. Als de argument een string bevat die je als integer of float zou kunnen interpreteren, dan krijg je die float terug als waarde. Anders krijg je een foutmelding.
x = 2
y = 3.1
z = 'Dit is een zin.'
print( float( x ) )
print( float( y ) )
print( float( z ) )
str()
heeft één argument en retourneert een string representatie van de waarde van het argument.
x = 2
y = 3.1
z = 'Dit is een zin.'
print( str( x ) )
print( str( y ) )
print( str( z ) )
abs()
is de ‘absolute waarde’ functie, en krijgt een integer of float als argument. Als die waarde positief is, wordt hij onveranderd geretourneerd. Als de waarde negatief is, wordt de waarde vermenigvuldigd met -1 geretourneerd.
x = 2
y = -3.1
print( abs( x ) )
print( abs( y ) )
max()
krijgt twee of meer numerieke argumenten (integer of float) en retourneert de grootste.
min()
krijgt twee of meer numerieke argumenten (integer of float) en retourneert de kleinste.
x = 2
y = 3.1
print( max( x , y ) )
print( min( x , y ) )
pow()
krijgt twee numerieke argumenten (integers of floats) en retourneert het eerste argument tot de macht het tweede argument. Optioneel kun je bij de pow()
functie een derde argument meegeven, die een integer moet zijn. Onderzoek zelf eens wat de invloed van het derde argument is.
round()
krijgt een numeriek argument (integer of float) die wiskundig wordt afgerond. Als er slechts één argument wordt meegegeven, wordt afgerond tot op de dichtstbijzijnde integer. Optioneel kun je bij de round()
functie een tweede argument meegeven, die een integer moet zijn. Dat optionele tweede argument geeft aan hoeveel cijfers achter de komma behouden moeten worden.
x = 3.1415
print( round( x ) )
print( round( x, 2 ) )
input()
In veel programma’s wil je dat de gebruiker van het programma de juiste gegevens ingeeft. In de code kun je de gebruiker vragen een string in te typen met behulp van de functie input()
. De functie krijgt één argument mee, namelijk een string. Deze string is de zogeheten “prompt”. Als input()
wordt aangeroepen, wordt de prompt op het scherm gezet en mag de gebruiker een tekst ingeven. De gebruiker mag ingeven wat hij of zij wil, inclusief niks. De gebruiker sluit het ingeven af met een druk op de Enter toets. De retour waarde van de functie is hetgeen de gebruiker heeft ingegeven, exclusief de Enter.
tekst = input( "Geef een tekst in:" )
print( "Je hebt het volgende ingetypt:" , tekst )
print( "De ingegeven tekst is van het datatype:" , type( tekst ) )
print()
krijgt nul of meer argumenten mee, toont ze op het scherm (als het er meerdere zijn, met spaties ertussen), en gaat daarna naar de volgende regel. Dus als je twee print statements gebruikt, komt de output van de tweede onder die van de eerste te staan. Als print()
wordt aangeroepen zonder argumenten, gaat de functie alleen naar de volgende regel. Zo kun je lege regels op het scherm zetten. Je mag als argumenten meegeven wat je wilt, en print()
zal zijn best doen het op het scherm weer te geven. Vooralsnog zul je echter alleen basis datatypes printen. print()
kan twee speciale argumenten meekrijgen, die sep en end heten:
print()
functie. Zo zal:
print ( "X" , "X" , "X" )
print ( "X" , "X" , "X" , sep="-" )
eerst als output X X X printen (standaard met spaties tussen de argumenten). Op de tweede lijn komt echter X-X-X.
print()
moet tonen nadat alle argumenten zijn getoond, wat standaard een nieuwe regel is. Je kunt er zelf voor zorgen dat print()
iets anders doet dan naar een nieuwe regel gaan als hij klaar is met het tonen van de argumenten. Dit doe je door end=”kies een symbool” als extra argument mee te geven binnen de print()
functie. Bijvoorbeeld:
print ( "X" , end = ";" )
print ( "X" , end = ";" )
print ( "X" )
Hoewel we drie print commando’s in de code hebben, wordt toch maar één lijn output geprint: X;X;X. Dit omdat de eerste twee print commando’s eindigen met een dubbelpunt in plaats van een (standaard) volgende lijn.
Merk op, om sep en end te gebruiken in de print()
functie, moet je “keyword” argumenten opnemen. Hier is niet de juiste volgorde van belang zoals gewone argumenten, maar gebruik je keywords om te verduidelijken welk argument volgt na het gelijkheidsteken. Keyword argumenten komen altijd na alle gewone argumenten. Heel vaak zijn keyword argumenten optioneel, worden ze niet expliciet meegegeven, dan is er altijd een standaard (En: default). Bij het keyword argument sep is de default een spatie, bij het keyword argument end is de default een nieuwe lijn.
Python biedt basis functies, waarvan een aantal hierboven besproken.
Helaas zijn echter niet alle functies rechtstreeks toegankelijk.
Zo bestaat er geen vierkantswortel()
functie in python
(Terzijde: de vierkantswortel functie mag dan misschien niet bestaan, we kunnen natuurlijk wel de pow()
functie met \(\frac{1}{2}\) als tweede argument gebruiken, want \(\sqrt{x} = x^{\frac{1}{2}}\)).
Toch kunnen we heel eenvoudig een vierkantswortelfunctie aanroepen, als we weten waar die ‘verstopt’ zit. Nee - Python speelt niet graag verstoppertje, maar ‘verstopt’ functies om het bos door de bomen te blijven zien. Er zijn namelijk vele duizenden functies beschikbaar. Met uitzondering van sommige basis ingebouwde functies zoals de voorbeelden hierboven, zitten alle beschikbare functies mooi geordend in modules. Alle machines (functies) zitten als het ware in lades (modules) van een grote kast in de garage (RAM geheugen). Onze pannenkoekenfunctie bijvoorbeeld kunnen we terugvinden in de ‘dessert’-lade. Als we die lade openen, zullen we daar misschien ook de wafelsfunctie en chocomoussefunctie terugvinden.
Om de functies van een module te gebruiken in jouw programma, moet je de juiste module importeren (lade openen), waarna je toegang krijgt tot alle functies binnen de geïmporteerde module. Importeren en functies uit modules gebruiken doe je zo:
import math
a = math.sqrt( 9 )
print( a )
Hierbij vallen enkele belangrijke syntax regels meteen op. Het importeren van de module (hier math, een lade vol wiskundige functies) vindt altijd plaats bovenaan het stuk code, ongeacht van de lengte van de code. Al schrijven we een script met duizend lijnen en hebben we een functie uit de math module pas op het einde nodig, dan nog wordt math reeds van bij het begin geïmporteerd. Om een functie uit de math module te gebruiken, moeten we Python steeds duidelijk maken waar we de functie vandaan halen. Dit gebeurt door middel van een punt tussen de modulenaam en de functienaam: math.sqrt()
. (Merk op: sqrt is een engelstalige afkorting voor square root, wat vierkantswortel betekent.) Het punt wordt in Python dus niet enkel als decimaalteken gebruikt, het is ook voorbehouden voor functie aanroepen vanuit modules. Verder is het gebruik van ingebouwde functies en module functies hetzelfde. De modulenaam.functienaam()
wordt altijd gevolgd door een paar haakjes, binnen dewelke argumenten worden opgelijst. Al is er geen enkel argument, dan nog zijn de haakjes verplicht. Meerdere argumenten binnen de haakjes worden gescheiden door komma’s. De volgorde van argumenten is cruciaal, tenzij het over keyword argumenten gaat. De retourwaarde van de functie kunnen we opslaan in een variabele (in het bovenstaande voorbeeld eenvoudigweg a genoemd), of rechtstreeks gebruiken.
Soms hebben modules vrij lange namen. Dat zou betekenen dat we telkens wanneer we een functie uit die module willen gebruiken, we de hele modulenaam.functienaam()
moeten typen, wat op den duur wel tijd kost. We kunnen dit vermijden door een afkorting (of “alias”) voor de module te bedenken, en die door middel van het gereserveerde Pythonwoord as
in te voeren. De afkortingsnaam kunnen we in principe zelf kiezen. Toch worden vele modules quasi altijd met dezelfde naam afgekort. Zo vaak zelfs dat vele programmeurs wel de afkorting, maar niet de échte modulenaam onthouden. Twee modules die we in de toekomst nog vaak zullen ontmoeten zijn numpy en matplotlib.pyplot, gebruikt voor respectievelijk numerische berekeningen en grafische voorstellingen en figuren. We kunnen die als volgt importeren:
import numpy as np
import matplotlib.pyplot as plt
# daarna kunnen we de functies van deze modules als volgt gebruiken :
np.mean() # voorbeeld, voorlopig nog zonder argumenten
plt.imshow() # voorbeeld, voorlopig nog zonder argumenten
Je mag er van uitgaan dat voor ieder min-of-meer-algemeen probleem dat je wilt oplossen, er iemand is geweest die er een module voor ontwikkeld heeft met functies die het eenvoudig of zelfs triviaal maken om het probleem op te lossen. Dus in de praktijk geldt: ga niet meteen alles zelf coderen, maar zoek eerst even uit of je niet gebruik kunt maken van de moeite die iemand anders gedaan heeft!