Wat in dit deel aan bod komt:
Aan de hand van een reeks voorbeelden leggen we wat uit over programmeren in Python.
Hyperlinks waarvan de achtergrond verkleurt bij aanwijzen, leiden naar een externe webplek.
Voor de liefhebbers: Python 2.2.2 was het uitgangspunt; bijgewerkt voor Python 2.3.3.
Waar het om gaat:
Waar je iets van moet leren:
Als gereedschap kun je gebruiken:
Mogelijke Python IDEs:
Hulp bij kiezen en installeren van een Python IDE zullen we hier niet bieden. Het gebruik van zo'n IDE spreekt meestal voor zich en komt summier aan de orde.
In het Engels zijn er ook heel andere inleidingen tot programmeren in Python. Zie bijvoorbeeld de "officiële" Python Tutorial (Nederlandse vertaling: Python Tutorial; niet meer beschikbaar) of kies iets uit de Beginners Guide. Als je nog niets van programmeren weet is Learning to Program van Alan Gauld aan te bevelen. Als je spelletjes (maken) leuk vindt, kun je terecht bij Pygame.
Alvorens zelf te gaan programmeren is het goed wat te weten van automaten. Denk aan een koffie-automaat of een mechanisch polshorloge.
Een automaat
Het polshorloge
Een computer is een programmeerbare automaat. De computer gedraagt zich als de automaat die beschreven is in een programma. Het programma is eenvoudig te vervangen. Daarom zullen we doen alsof
De belangrijkste onderdelen van een computer zijn:
De interne toestand van de nagespeelde automaat wordt in het geheugen opgeslagen. De processor doet de berekeningsstappen van de nagespeelde automaat in samenwerking met het geheugen en de I/O-eenheid.
Verderop vertellen we meer over programmeertalen. Nu volstaat het om te weten dat een programmeertaal een notatie is om een automaat te beschrijven.
We volgen de levensloop (Eng.: life cycle) van een klein programma aan de hand van een eenvoudig voorbeeld. We doorlopen de volgende fasen:
Dit is leesvoer. Daarna komen wat oefeningen om zelf te doen.
De probleemstelling zet het probleem uiteen in termen van de wereld waarin het zich afspeelt. In ons voorbeeld:
Hoe kun je een gegeven bedrag gepast betalen met zo min mogelijk euromunten?
Zo kun je 96 eurocent gepast betalen met 5 euromunten:
één halve euro ( 1 x 50 eurocent ) twee kwintjes ( 2 x 20 eurocent ) één stuiver ( 1 x 5 eurocent ) één cent ( 1 x 1 eurocent )
Met minder munten lukt het niet.
De specificatie legt vast waaraan een programma moet voldoen om als "oplossing" van het probleem te kunnen fungeren.
De belangrijkste vragen die een specificatie dient te beantwoorden zijn:
Het is vaak ook nuttig voorbeeld-dialogen te geven. In ons voorbeeld kiezen we voor de volgende specificatie:
- Invoer:
- Bedrag in eurocenten, tussen 0 en 500
- Uitvoer:
- Tabel met het aantal keer dat iedere munt gebruikt is om het ingevoerde bedrag met zo min mogelijk euromunten gepast te betalen
- Beperkingen:
- Onbeperkt beschikbare euromunten met de volgende waarden (in eurocenten):
1, 2, 5, 10, 20, 50, 100, 200Ongebruikte munten worden niet in de tabel vermeld.- Voorbeeld dialoog (invoer is geel, uitvoer is blauw):
96 1 x 50 2 x 20 1 x 5 1 x 1
Het ontwerp legt in abstracte (wiskundige) termen uit hoe het probleem opgelost kan worden en waarom het een oplossing is.
Bij kleine programma's komt dit neer op een beschrijving van
Hier is een mogelijk ontwerp voor ons voorbeeld:
- Variabelen:
- Gehele getallen bedrag (invoer en nog te passen restbedrag), munt (om muntsoorten te doorlopen) en aantal (om te tellen hoe vaak munt gebruikt is).
- Stappen:
- Lees bedrag in
- Laat munt de waarden van de euromunten dalend doorlopen
- Bepaal voor elke munt het maximale aantal dat gebruikt kan worden om het resterende bedrag gepast te betalen en verlaag het bedrag met elke gebruikte munt
- Schrijf aantal x munt, mits aantal > 0
Dat dit ontwerp inderdaad aan de voorgaande specificatie voldoet, d.w.z. een minimale gepaste betaling bij het ingevoerde bedrag levert, zullen we hier niet beargumenteren. Waarschijnlijk is dit de manier waarop de meeste eurogebruikers het doen.
In de productie-fase wordt het ontwerp gecodeerd in een programmeertaal die de computer kan verwerken. Het product noemen we (programma)code. Het produceren van code wordt ook wel coderen, implementeren of realiseren genoemd.
Hieronder staat de code van een Python programma bij ons voorgaande ontwerp. We leggen verderop meer uit over de notatie en de werking. Je kan het programma ook ophalen: gepast0.py, maar wacht daar nog even mee. Lees het eerst een keer door en vergelijk het met het voorgaande ontwerp:
# Een bedrag gepast betalen met zo min mogelijk euromunten bedrag = input ( 'Geef bedrag tussen 0 en 500 eurocent: ' ) for munt in 200, 100, 50, 20, 10, 5, 2, 1 : aantal = 0 while bedrag >= munt : aantal = aantal + 1 bedrag = bedrag - munt if aantal > 0 : print aantal, 'x', munt
In iedere fase moet je controleren of die goed verloopt en goed afloopt. Bij dit kleine programma beperken we ons tot het controleren van de code. Deze controle bestaat uit
Dat uitproberen wordt ook testen genoemd. Op grond van de specificatie en het ontwerp kunnen we een aantal testgevallen (Eng.: test cases) bedenken en die vermelden in een testplan:
Testplan voor gepast betalen | |||
---|---|---|---|
Nr. | Invoer bedrag | Verwachte uitvoer (tabel) | Toelichting |
1 | 0 | (geen) | Kleinste bedrag volgens specificatie |
2 | 1 | 1 x 1 | Kleinste betaling met één munt |
3 | 3 | 1 x 2 1 x 1 |
Kleinste betaling met twee verschillende munten |
4 | 4 | 2 x 2 | Kleinste betaling met tweemaal dezelfde munt |
5 | 200 | 1 x 200 | Kleinste betaling met éénmaal de grootste munt |
6 | 388 | 1 x 200 1 x 100 1 x 50 1 x 20 1 x 10 1 x 5 1 x 2 1 x 1 |
Kleinste betaling met éénmaal elke munt |
7 | 500 | 2 x 200 1 x 100 |
Grootste bedrag volgens specificatie |
Behalve geschikte invoer, dient ook de bijbehorende verwachte uitvoer vermeld te worden, alsmede een reden voor de keuze. We zullen later wel zien dat bovenstaande gevallen nog niet genoeg zijn voor een echt serieuze controle!
Als bij de controle eventuele defecten in het product ontdekt worden, dan is het zaak deze defecten te elimineren. (Dit behandelen we verder in Deel 2.)
Als je ervan overtuigd bent dat het product geen defecten meer bevat, dan kan het in gebruik genomen worden.
Bij de oefeningen hieronder mag je dat zelf doen met ons voorbeeld-programma.
Een programma slijt niet, ook niet door intensief gebruik. Toch is er bij programma's behoefte aan onderhoud:
Onderhoud aan een programma bestaat uit het doorvoeren van aanpassingen om tegemoet te komen aan veranderingen in omgeving en wensen. Hiervoor worden alle fasen nogmaals doorlopen. Dit doen we verderop.
Als een programma niet meer aan te passen is, dan wordt het afgedankt. Daar hoor je meestal niets over.
Nu is het tijd om zelf wat te gaan proberen.
Invoer Foutmelding 96abc SyntaxError: Unexpected EOF while parsing ... abc NameError: name 'abc' is not defined ... 'abc' TypeError: unsupported operand type(s) for -: 'str' and 'int' ...
N.B. Hoe de foutmeldingen precies gepresenteerd worden hangt af van de Python IDE die je gebruikt.
Bij het bestuderen van een (programmeer)"taal" is het nuttig om drie aspecten te onderscheiden:
Denk aan verkeerslichten als "taal" om berichten naar bestuurders over te brengen. Er zijn allerlei soorten, veelal met rode, gele en groene lichten, waarvan de verschijningsvormen afhangen van de doelgroep (auto's, voetgangers, bussen, treinen, etc.). Ze brengen betekenissen over als Stop, Pas op en Ga. In de praktijk blijken ze vaak anders gebruikt te worden dan in de wet is vastgelegd.
De syntactische bouwstenen van Python programmateksten vallen in zeven categorieën:
Categorie | Voorbeeld |
---|---|
Commentaar | # Een bedrag gepast betalen met ... |
Wit | regelovergang, spatie, tab |
Namen | bedrag input munt aantal |
Sleutelwoorden | for in while if print |
Letterlijke waarden | 200 100 50 20 10 5 2 1 0 'x' |
Operatoren | >= + - > |
Scheiders | = ( ) , : |
In de tabel zijn koppelingen opgenomen naar de "officiële" documentatie van de programmeertaal Python. Je hoeft dat niet allemaal te begrijpen, maar je kan er allicht iets van opsteken.
Belangrijke semantische bouwstenen van Python programma's zijn:
Categorie | Toelichting | Voorbeeld | |||||
---|---|---|---|---|---|---|---|
Naam-object bindingen | Op elk moment refereert iedere naam aan één object |
| |||||
Uitdrukkingen | Worden geëvalueerd tot een object |
| |||||
Enkelvoudige opdrachten | Worden uitgevoerd |
| |||||
Samengestelde opdrachten | Worden uitgevoerd afhankelijk van de toestand |
|
Hier volgt een korte toelichting bij de betekenis van Python uitdrukkingen (Eng.: expressions) en opdrachten (Eng.: statements):
Met behulp van deze semantische bouwstenen is alles wat programmeerbaar is ook te programmeren. We behandelen in de volgende delen nog wel meer, maar die uitbreidingen dienen alleen het programmeergemak; ze voegen geen essentiële nieuwe mogelijkheden toe.
Hieronder volgt een tabel met het waardenverloop bij uitvoering van gepast0.py met invoer 96. Een '?' staat voor een ongedefinieerde waarde. Een groene achtergrondskleur duidt op een nieuw toegekende waarde.
Invoer en Uitvoer | bedrag | munt | aantal | Conditie | Toelichting |
---|---|---|---|---|---|
Geef bedrag ... | ? | ? | ? | ... input ( 'Geef bedrag ...' ) | |
96 | ? | ? | ? | ingetikt door gebruiker | |
96 | ? | ? | bedrag = ... | ||
96 | 200 | ? | for munt in 200, ... : | ||
96 | 200 | 0 | aantal = 0 | ||
96 | 200 | 0 | False | while bedrag >= munt : | |
96 | 200 | 0 | False | if aantal > 0 : | |
96 | 100 | 0 | for munt in ..., 100, ... : | ||
etc. etc. |
Met betrekking tot goede programmeergewoontes (en die gelden niet alleen voor programmeren in Python) vermelden we:
Nette opmaak | Spaties, bijv. rond namen, operatoren en =,
en na komma's; lege regels, bijv. vóór en na herhalingen met for en while; systematisch inspringen |
Helder commentaar | Vermelding van programmadoel, auteur(s) en datum; toelichting bij variabelen en stappen |
Zinvolle namen | Gerelateerd aan hun doel |
Geschikt interface | Toelichtende tekst laten schrijven bij interactief inlezen van waarden; nette uitvoer schrijven |
Systematisch controleren | programmatekst vergelijken met ontwerp; programma uitproberen met vooraf gekozen testinvoer en vooraf bekende testuitvoer |
Ons eerste voorbeeld programma gepast0.py heeft een nette opmaak, bevat commentaar, gebruikt zinvolle namen en heeft een geschikt interface. Ook hebben we systematische tests gegeven. Het commentaar en interface zijn voor verbetering vatbaar. Dat zien we in het volgende deel.
Bovengenoemde goede gewoontes vergen enige inspanning vooraf en de meerwaarde is misschien niet meteen duidelijk. Maar ze zijn in de loop der jaren ontstaan, omdat gebleken is dat ze helpen bij het maken van betere programma's. In een rommelig programma maak je veel makkelijker fouten die veel lastiger te vinden zijn. Achteraf "oppoetsen" van een programma kost meer moeite dan het meteen netjes doen.
Als afschrikwekkend voorbeeld volgt hier een Python programmatekst gepast0a.py die syntactisch anders is, maar semantisch hetzelfde als het eerder gegeven voorbeeld. Het heeft minimaal wit, geen commentaar, gebruikt de kortste namen en heeft een karig interface:
a=input() for b in 200,100,50,20,10,5,2,1: c=0 while a>=b: c=c+1 a=a-b if c>0: print c,b
Niet veel mensen zullen bereid zijn je te helpen met het zoeken naar fouten in zo'n programma! Vergelijk het nog maar eens met het eerste product.
Hier volgen nog wat meer oefeningen.
Geef bedrag tussen 0 en 500 eurocent: 96 1 x 50 2 x 20 1 x 5 1 x 1 Aantal munten: 5
Introduceer hiervoor een nieuwe variabele met naam totaal en als doel het totale aantal gebruikte munten te tellen (dit is een uitbreiding van het ontwerp).
Wijzig vervolgens de code en test het resulterende programma.
Kopieer eerst het programma gepast0.py naar gepast0b.py. (De namen van Python programma's kunnen het beste op .py eindigen.) Open de kopie, breng de wijzigingen aan en bewaar (Eng.: save) de gewijzigde versie.
N.B. Als je bij het wijzigen iets verkeerd doet, kun je bij het uitvoeren van het programma een foutmelding krijgen. Zo moeten opdrachten die in een blok bijelkaar horen even ver ingesprongen zijn.
Pas in het voorgaande programma de muntwaarden aan tot die voor het oude Nederlandse geld zonder kwartje:
5, 10, 100, 250, 500Het invoerbedrag dient nu een 5-voud te zijn, anders kan het natuurlijk niet gepast worden. Bedenk (nieuwe) testgevallen en probeer ze uit. Zoek ook invoer waarvoor de betaling niet klopt of niet minimaal is.
In de levensloop van een programma hebben we de volgende fasen onderscheiden:
Van de programmeertaal Python hebben we met de volgende onderdelen kennisgemaakt:
Commentaar | ||
---|---|---|
# tekst | Commentaar | Vanaf # wordt de tekst tot het einde van de regel genegeerd |
Uitdrukkingen | ||
naam | Uitdrukking | De waarde van het object waar de naam aan gebonden is |
letterlijke waarde | Uitdrukking | De letterlijke waarde zelf |
uitdrukking operator uitdrukking | Uitdrukking | De operator wordt toegepast op de waarden van de uitdrukkingen |
( uitdrukking ) | Uitdrukking | De waarde van de uitdrukking; doorbreekt de standaardvolgorde van evaluatie |
functie ( lijst uitdrukkingen ) | Uitdrukking | De waarde geretourneerd door de functie aangeroepen met de lijst uitdrukkingen als argumenten |
Uitvoer | ||
print lijst uitdrukkingen | Enkelvoudige opdracht | De lijst uitdrukkingen wordt geëvalueerd tot karakterrij en dan geschreven; elementen worden gescheiden door één spatie; bij interactief gebruik kan print worden weggelaten |
Invoer | ||
input ( karakterrij ) | Ingebouwde functie | Schrijft de opgegeven karakterrij en retourneert een ingelezen, geëvalueerde karakterrij |
Opeenvolging | ||
opdracht opdracht |
Blok opdrachten | Opdrachten die onder elkaar staan worden van boven naar beneden uitgevoerd |
Toekenning | ||
naam = uitdrukking | Enkelvoudige opdracht | De geëvalueerde uitdrukking wordt aan de naam toegekend |
Conditionele Uitvoering (Selectie) | ||
if uitdrukking : ingesprongen blok opdrachten |
Samengestelde opdracht | Als de uitdrukking geldt, wordt het ingesprongen blok opdrachten (eenmalig) uitgevoerd |
Onconditionele Herhaling | ||
for naam in lijst uitdrukkingen : ingesprongen blok opdrachten |
Samengestelde opdracht | Elementen uit de lijst uitdrukkingen worden achtereenvolgens toegekend aan naam en hierna wordt telkens het ingesprongen blok opdrachten uitgevoerd. |
Conditionele Herhaling | ||
while uitdrukking : ingesprongen blok opdrachten |
Samengestelde opdracht | Zolang de uitdrukking geldt, wordt het ingesprongen blok opdrachten (herhaaldelijk) uitgevoerd |
Met een Python IDE hebben we het volgende gedaan:
Als goede programmeergewoonten zijn we tegengekomen: