L E S B O E K J E. Jochum. van Weert Wt (at) sgdb.nl Stedelijk Gymnasium s-hertogenbosch v Delen onder Creative Commons toegestaan

Vergelijkbare documenten
L E S B O E K J E. J. van Weert Wt (at) sgdb.nl Stedelijk Gymnasium s-hertogenbosch Wt /

BEGINNER JAVA Inhoudsopgave

Een spoedcursus python

Inleiding Programmeren 2

Je gaat leren programmeren en een spel bouwen met de programmeertaal Python. Websites zoals YouTube en Instagram zijn gebouwd met Python.

Kleine cursus PHP5. Auteur: Raymond Moesker

Zo gaat jouw kunstwerk er straks uitzien. Of misschien wel heel anders.

Inleiding Programmeren 2

Datatypes Een datatype is de sort van van een waarde van een variabele, veel gebruikte datatypes zijn: String, int, Bool, char en double.

Simon de schildpad J van Weert 1

[15] Variabelen in functies (of: een woordje over scope)

Practicumopgave 3: SAT-solver

Hoofdstuk 6: Zelf functies maken

Het project Gamemaker Kids is mede mogelijk gemaakt door:

Stap 1. Bepalen van invoer Het makkelijkst kun je dit vinden uit de zwarte vlakken met voorbeelden:

Verder zijn er de nodige websites waarbij voorbeelden van objectgeoriënteerd PHP (of Objec Oriented PHP, OO PHP) te vinden zijn.

Programmeermethoden NA. Week 5: Functies (vervolg)

Herhaling. Individuele Oefening. Individuele oefening. Tips en technieken in Alice. Vis in de zee Houdt van zeewier

Stroomschema s maken op papier

Object Oriented Programming

MINICURSUS PHP. Op dit lesmateriaal is een Creative Commons licentie van toepassing Sebastiaan Franken en Rosalie de Klerk Bambara

Programmeermethoden NA. Week 5: Functies (vervolg)

Uitwerking Tweede deeltentamen Imperatief programmeren - versie 1 Vrijdag 21 oktober 2016, uur

Een gelinkte lijst in C#

Simon de schildpad J van Weert 1

Variabelen en statements in ActionScript

Android apps met App Inventor 2 antwoorden

JavaScript. 0 - Wat is JavaScript? JavaScript toevoegen

Functioneel programmeren

PO: Informatica Olympiade

[14] Functies. Volg mee via 14_Functies-1.py. We beginnen met een eenvoudig voorbeeldje:

Ga naar en remix dit project.

HET OPSTELLEN VAN USER EN HET UITSPLITSEN VAN USER STORIES NAAR CONCRETE TAKEN.

Getting Started with Python Programming

ontwerpdocumentatie doelgroep

Modelleren en Programmeren

Programmeren A. Genetisch Programma voor het Partitie Probleem. begeleiding:

Programmeren. a. 0, 0, 0 b. 0, 0, 27 c. 15, 12, 0 d. 15, 12, 27

STROOMDIAGRAMMEN. Hoofdstuk 8. Hoe je Galgje moet spelen. Voorbeelduitvoer van Galgje. Hoofdstuk 8 Stroomdiagrammen 67

Toetsvoorbereiding Informatica HAVO/VWO 5 (T51) Programmeren met Python II. Duur: 70 minuten Datum: sept 2018

Disclaimer Het bestand dat voor u ligt, is nog in ontwikkeling. Op verzoek is deze versie digitaal gedeeld. Wij willen de lezer er dan ook op wijzen

HOOFDSTUK 3. Imperatief programmeren. 3.1 Stapsgewijs programmeren. 3.2 If Then Else. Module 4 Programmeren

Je gaat leren programmeren in Ruby. En daarna in Ruby een spelletje maken. Websites zoals Twitch en Twitter gemaakt zijn met behulp van Ruby?

Meer Blokken. 1. Dit is een functie genaamd Maximum, die twee argumenten heeft: number1 en number2.

Fase Ontdek en onderzoek

Hoofdstuk 5. Extra basisscherm-onderwerpen

Informatica. Objectgeörienteerd leren programmeren. Van de theorie met BlueJ tot een spelletje met Greenfoot... Bert Van den Abbeele

Tentamen Imperatief en Object-georiënteerd programmeren in Java voor CKI

Hoofdstuk 6: Zelf functies maken

Als een PSD selecties bevat, deelt de lijn van het programma zich op met de verschillende antwoorden op het vraagstuk.

afrondende suggesties worden gebruikt om dieper op het onderwerp in te gaan als daar tijd voor is.

Opgaven. Python Assessment

DE INTERACTIEVE SHELL

algoritmiek - antwoorden

Fable Robotica Lesgids

Scratch les 3: Quiz! Je eigen spelshow

[13] Rondjes draaien (loops)

HOOfDsTuk 1 Objecten en klassen

Opdracht 7a. Applicatiebouw 2014/2015

Inhoud. Blz. 3. Blz. 4. Blz. 5. Blz. 7. Blz. 8. Blz. 9. Blz. 10. Opdracht 1 - Brainstormen. Opdracht 2 - Je eigen controller. informatie - makey makey

Uitwerking Aanvullend tentamen Imperatief programmeren Woensdag 24 december 2014, uur

Programmeerstructuren met App Inventor

extra oefening algoritmiek - antwoorden

Het relaas van de beginnende programmeur. Het hoe en waarom van de assistent

1 Inleiding in Functioneel Programmeren

Uitleg: In de bovenstaande oefening zie je in het eerste blokje een LEES en een SCHRIJF opdracht. Dit is nog lesstof uit het tweede trimester.

Schrijfopdracht 5: Zijn vrienden het altijd eens?

GEVORDERDE PROGRAMMEER LES

VBA voor Doe het Zelvers deel 9

Visual Basic.NET. Visual Basic.NET. M. den Besten 0.3 VB. NET

Tentamen Imperatief Programmeren

II. ZELFGEDEFINIEERDE FUNCTIES

Programmeermethoden NA

Datastructuren Werkcollege Intro

Gebruiksvriendelijkheid: Gebruiksaanwijzing:

Methods of Development

Hoofdstuk 7: Werken met arrays

VI. Klassen en objecten

P O P Y T H O N P R O G R AMMER EN: G A N Z E N B O R D

Programmeermethoden NA

In de tweede regel plaatsen we in het gereserveerde stukje geheugen een getal.

ALGORITME objectgeoriënteerd programmeren

Tentamen Objectgeorienteerd Programmeren IN1205 Voorbeeld

PIM 2013 VU. One day in Amsterdam. Martijn van der Burg MBG215

Inhoudsopgave Voorwoord 5 Nieuwsbrief 5 Introductie Visual Steps 6 Wat heeft u nodig? 6 Voorkennis 7 Hoe werkt u met dit boek?

Stroomschema s maken in Word

Let s play baseball! Let s get ready! Voorkennis: Sprites, Lopen, Variabelen, Scores, xy. Leerdoelen: 3D illusie, Klonen

PHP-OPDRACHT SITE BOUWEN

R-Type 2009 Developing in XNA

U kunt een waardebon toepassen op alle klanten, op een klantengroep of op een enkele klant; u kunt de vervaldatum bepalen.

Scratch in drie uur. Hallo, mijn naam is Minti Mint! Ik ga je uitleggen hoe je je eigen computerspel kunt maken. We gaan een racespel maken!

Word cursus tekstverwerken - Hoofdstuk 3

Er wordt door veel mensen opgezien tegen de overstap

Wat ga je schrijven: een verklarende tekst. Filmpje kijken en aantekeningen maken

Het programma in dit hoofdstuk vertelt een paar moppen aan de gebruiker.

Zoemzinnen. Algemene info. Functies met een variabel aantal argumenten

Een stop-motion film maken

afrondende suggesties worden gebruikt om dieper op het onderwerp in te gaan als daar tijd voor is.

DE ASTRO PI PROGRAMMEREN VOOR MISSION ZERO

5. Geavanceerde formules

Transcriptie:

W T S A D V A N C E D P Y T H O N L E S B O E K J E Jochum. van Weert Wt (at) sgdb.nl Stedelijk Gymnasium s-hertogenbosch v2.0 2017 Delen onder Creative Commons toegestaan 1

INHOUD 1 Inleiding... 3 2 Object Oriented Programming (OOP)... 4 2.1 Classes... 4 2.2 Init en methoden met parameters... 5 2.3 Standaard waarden voor functieparameters... 6 2.4 Class variables en instance variables... 8 2.5 Overerving... 9 2.6 Methoden van je parent aanpassen... 10 2.7 Meervoudige overerving... 12 2.7.1 Multiple inheritance probleem 1: conflicterende methoden... 12 2.7.2 Multiple inheritance probleem 2: meerdere init () methoden... 13 3 Error handling... 14 3.1 Inleiding... 14 3.2 Soorten foutmeldingen... 15 3.3 Exceptions... 16 4 PO: text-based RPG... 17 4.1 Inleiding... 17 4.2 Groepjes... 17 4.3 Aanpak... 17 4.4 Beoordeling... 18 4.5 Tips voor uitbreidingen... 18 5 Links en vervolgsuggesties... 20 2

1 INLEIDING Je hebt inmiddels aardig wat ervaring met Python. Toch valt er nog oneindig over te leren (veel meer nog dan we hier nog kunnen toevoegen). In dit boekje breiden we je programmeerarsenaal uit met 2 belangrijke concepten: Objects en Error Handling. Objects bieden je een andere manier om je code op te bouwen. Alles wat je tot nu toe geleerd hebt is nog steeds geldig en relevant, maar het indelen van je code in Objects heeft een aantal voordelen: - Objecten bieden extra structuur en maken daarmee je code overzichtelijker - Objecten helpen je voorkomen dat je code herhaalt. Dit voorkomt fouten en maakt je code beter te onderhouden - Objecten maken code recyclebaar: objecten die je eerder geschreven hebt, kun je gemakkelijk in nieuwe programma s importeren en er op voortbouwen. - Objecten maken het makkelijker je code in stukken te verdelen en daarmee is het makkelijker om samen te werken aan code (ieder zijn eigen afgesloten stuk) Error handling is een mechanisme dat helpt om fouten die kunnen optreden tijdens het gebruik van een programma (bijvoorbeeld ongeldige invoer van een gebruiker) op een goede manier af te handelen, zonder dat de gebruiker wordt overladen met cryptische foutmeldingen. Je maakt je eerst de fijne kneepjes van bovenstaande onderwerpen eigen. Daarna gaan we uiteraard je nieuwe skills loslaten op het bouwen van een game. 3

2 OBJECT ORIENTED PROGRAMMING (OOP) 2.1 CLASSES In OOP draait alles om classes (klassen) en objects/instances (objecten of instanties). Bekijk het volgende filmpje met een voorbeeld en uitleg over de basics van Python classes: Thenewboston Tutorial 29: Classes and Objects Hierin leer je: - Basis class syntax (schrijfwijze) - Class variables - Class functions (+self) - Instanties (objects) maken - Het maken van meerdere instanties (objects) van een klasse en het gebruik ervan Opdracht 1: Bouw de Enemy() class na uit het filmpje. Breid de Enemy() klasse uit met een nieuwe functie heal(). Deze functie verhoogt de life van de enemy met 2. Test je functie door een Enemy object te maken, een paar keer de heal() en de attack() functies ervan uit te voeren en vervolgens met de checklife() functie de kijken of het goed heeft gewerkt. Opdracht 2: Wijzig de methode attack() zodanig dat elke attack een random getal tussen 0 en 3 kiest en dat van de life variabele afhaalt (schade is dus niet meer altijd 1, maar kan variëren). Schrijf vervolgens een programma dat twee objecten van het type Enemy maakt en ze om en om elkaar laat aanvallen (gebruik een loop). Als 1 van de 2 dood is, eindigt je programma met de melding wie er gewonnen heeft en hoeveel life de winnaar nog over heeft. NB: Kijk in de codecademy samenvatting hoe random ook alweer werkt. 4

2.2 INIT EN METHODEN MET PARAMETERS Bij het maken van een nieuw object is het vaak handig als meteen een stukje code wordt uitgevoerd dat de startwaarden van het object goed instelt. Hiertoe dient de speciale init () methode. Methodes kunnen natuurlijk (net als gewone functies) meerdere parameters hebben. Bekijk het volgende filmpje: Thenewboston Tutorial 30: Init Hierin leer je: - Werking van de speciale init () functie bij classes - (extra) parameters naast self voor functies Opdracht 3: Breid je Enemy() class van de vorige opdracht (opdracht 2) uit met een init () functie. Deze functie vraagt (naast de standaard benodigde self) om 2 parameters: het aantal levenspunten om mee te beginnen en de maximale schade die geïncasseerd kan worden per aanval (2 integers dus). Sla deze waarden op in variabelen van de class. Pas nu je attack() functie aan zodat de maximum schade die gedaan kan worden gelijk is aan het opgeslagen maximum uit de init() methode. De schade is dus een random getal tussen 0 en het maximum. Laat bij elke keer dat de attack() functie wordt aangeroepen ook op het scherm zien wat de schade was en hoeveel life de Enemy nog heeft. Test je code door weer in een loop 2 instanties van Enemy met elkaar te laten vechten tot er een dood is. Experimenteer met verschillende waarden voor de init methodes van de beide Enemy objecten. 5

2.3 STANDAARD WAARDEN VOOR FUNCTIEPARAMETERS (Geen filmpje bij dit stukje stof helaas. Wt wil ze zelf gaan maken, maar vooralsnog geen tijd gehad ) Zoals je weet heeft een functie parameters. Dat zijn de waarden die je de functie meegeeft als je hem gebruikt (aanroept). Dit geldt zowel voor functies die onderdeel zijn van een class als voor gewone functies. Voor de duidelijkheid een simpel voorbeeld: def tel_op(a,b): return a+b In het voorbeeld zijn a en b de parameters. Een aanroep van de functie zou nu kunnen zijn: tel_op(10,86) En als antwoord zal de waarde 96 worden teruggegeven. In de aanroep hierboven is dus voor a de waarde 10 en voor b de waarde 86 opgegeven. De functie gebruikt de opgegeven waarden in zijn code. Soms kan het handig zijn om voor een functie een of meerdere standaardwaarden op te geven voor de parameters. Hiermee geef je de aanroeper van de functie de mogelijkheid om enkele parameters leeg te laten. Hiervoor wordt dan de standaardwaarde gebruikt. Een voorbeeld maakt dit duidelijk: def tel_op(a, b=20): return a+b In dit voorbeeld is in de functiedefinitie de waarde 20 als standaardwaarde opgegeven voor parameter b. Als we nu het volgende doen: tel_op(10,86) Krijgen we nog steeds hetzelfde antwoord: 96. Maar als we de waarde voor b weglaten als volgt: tel_op(10) Krijgen we als antwoord 30. Python verwacht 2 parameters, maar omdat er maar 1 gegeven is, gebruikt hij deze als waarde voor a en kiest hij de standaardwaarde (20) voor b. Simpel toch? Let op: Als een functie zowel parameters met standaardwaarde en parameters zonder standaardwaarde heeft, moeten die met standaardwaarde altijd achteraan. Dus: (1) def voorbeeld(a=10,b,c=20)is fout. (2) def voorbeeld(b,a=10,c=20)is goed. Als je er even over nadenkt, dan is dat logisch. Stel je hebt de (foute ) functiedefinitie van (1) en je doet de volgende aanroep: voorbeeld(13,14) Bedoel je nu dat a gelijk moet zijn aan 13, b aan 14 en c aan zijn standaardwaarde 20? Of bedoel je dat a gelijk is aan zijn standaardwaarde 10, b gelijk aan 13 en c gelijk aan 14? Dit is onduidelijk en dus niet toegestaan. 6

Als je de definitie van (2) hebt, dan is de aanroep wel duidelijk: voorbeeld(13,14) Dit betekent nu dat b gelijk is aan 13, a gelijk aan 14 en c gelijk aan zijn standaardwaarde 20 Opdracht 4: In opdracht 3 heb je een init () functie toegevoegd aan je Enemy() class. Ook een init () functie kan standaardwaarden hebben. Pas je init () functie uit opdracht 3 aan, zodat de parameters voor het aantal levenspunten om mee te beginnen en de maximale schade die geïncasseerd kan worden per aanval als standaardwaarde respectievelijk 20 en 3 krijgen. Test je nieuwe Enemy() object door verschillende enemies te maken, waarbij je soms wel en soms geen waarden voor de init () parameters opgeeft. 7

2.4 CLASS VARIABLES EN INSTANCE VARIABLES Er zijn verschillende termen voor variabelen die in een class gebruikt worden: - Class variables: Variabelen die in de klasse definitie worden gezet. De waarde hiervan is dus hetzelfde voor alle objecten (instanties) van deze klasse. - Instance variables: Variabelen die gemaakt worden in de init () methode van de klasse. Deze verschillen van waarde bij verschillende objecten (instanties) van deze klasse. (Vandaar ook de naam, instance variabelen hebben voor elke instance een unieke waarde) Niet super lastig, maar belangrijk om deze termen te kennen en uit elkaar te kunnen houden. Bekijk het volgende filmpje voor een korte uitleg met een voorbeeld: Thenewboston tutorial 31 Opdracht 5: Bekijk nog even je code van opdracht 4. Als het goed is heb je zowel class variables als instance variables gebruikt. Welke zijn welke? 8

2.5 OVERERVING Je hebt al gezien dat klassen een handige manier zijn om eenmalig een definitie van iets te schrijven (bijvoorbeeld de Enemy class uit de vorige opgaven) en meerdere objecten te maken die deze definitie gebruiken. Daar kunnen we nog een schepje bovenop doen met het principe van overerving (inheritance in het Engels). Bekijk het volgende filmpje: Thenewboston tutorial 32: Inheritance Hierin leer je: - De basics van inheritance (een klasse alle eigenschappen van een andere klasse laten overnemen en hier dingen aan toevoegen) - Overriding. Dit is het vervangen van een geërfde eigenschap (zoals een functie) door een andere invulling ervan. Het voorbeeldje uit het filmpje is simpel, maar inheritance is een erg krachtig concept. Je kunt zo een hele stamboom van classes maken die steeds specifieker worden. Hierdoor heb je nergens dubbele code, maar wel veel verschillende bruikbare classes met (deels) andere eigenschappen. Opdracht 6: Ga weer verder met je code uit opdracht 4. Maak een nieuwe class Boss en zorg dat dit een kindklasse is van de bestaande Enemy class. De Boss class erft nu dus alle variabelen en methoden van de Enemy class. Voeg de volgende dingen toe aan je Boss class: a. Een beetje eindbaas is natuurlijk ontzettend evil. Voeg een nieuwe methode evil_laugh() toe die Muhahahahah!! op het scherm afdrukt. b. De Boss class heeft een speciale eigenschap (het is tenslotte een eindbaas!) die hem moeilijker te verslaan maakt. Voeg een class variable met de naam shield toe aan de Boss. De waarde van shield is 3. c. Override de attack() methode die geërfd is van Enemy. Deze moet in de basis hetzelfde doen als de originele attack() methode van Enemy, maar met de volgende toevoeging: Als de Boss geraakt wordt en zijn shield variabele is groter dan 0, dan heeft hij 50% kans om de aanval af te weren en dus 0 schade te krijgen. Als dat gebeurt wordt zijn shield variabele met 1 verlaagd. (Zo kan hij dit maar 3x in totaal doen). Er wordt ook een melding afgedrukt dat de aanval geblokt is. Test je Boss door weer een gevecht te organiseren tussen een Boss en een Enemy., zoals je bij opdracht 3 gedaan hebt. Probeer ook eens een Boss tegen een Boss. 9

2.6 METHODEN VAN JE PARENT AANPASSEN (Geen filmpje bij dit stukje stof helaas. Wt wil ze zelf gaan maken, maar vooralsnog geen tijd gehad ) Hoewel het fijn is dat je methoden die je geërfd hebt kunt vervangen, gooi je daarmee soms ook veel nuttige code weg. Je schrijft namelijk de hele methode opnieuw, terwijl je soms gewoon een kleine toevoeging wilt doen aan de geërfde methode. Om dit te bereiken kun je de code van een methode van je parent weer oproepen als je als kindklasse de methode overschrijft. Bekijk het volgende voorbeeld: class Persoon: def init (self, voor, achter): self.voornaam = voor self.achternaam = achter def wie_ben_ik(self): print "Mijn naam is", self.voornaam, self.achternaam class Medewerker(Persoon): def init (self, voor, achter, stafnr): Persoon. init (self, voor, achter) self.stafnummer = stafnr def wie_ben_ik(self): Persoon.wie_ben_ik(self) print "en mijn stafnummer is:", self.stafnummer x = Persoon("Frits", "Worschtenbroodt") y = Medewerker("Hendrik", "Appelentaerte", 104) x.wie_ben_ik() y.wie_ben_ik() uitvoer: Mijn naam is Frits Worschtenbroodt Mijn naam is Hendrik Appelentaerte en mijn stafnummer is: 104 In de code zie je 2 klassen: Persoon en Medewerker. Medewerker is een kindklasse van Persoon en erft zowel de init () methode als de wie_ben_ik() methode van Persoon. Beide methoden worden in Medewerker overschreven door een nieuwe versie, maar op een andere manier dan tot nu: De code uit de originele methode van de parent wordt hierbij steeds eerst aangeroepen ( Persoon. init (self, voor, achter) en 10

Persoon.wie_ben_ik(self)) en vervolgens worden er nog dingen aan toegevoegd. De schrijfwijze hiervan lijkt op het gewoon aanroepen van een methode met 2 verschillen: - Je noemt de naam van de parent-klasse (in dit geval Persoon) in plaats van de naam van de instantie - De self parameter moet ook worden opgegeven Bekijk de code goed en zorg dat je goed begrijpt hoe het aanroepen van een methode van de parent werkt. Opdracht 7: Ga verder met je code uit opgave 6. a: In opgave 6 heb je de Boss class toegevoegd als subclass van Enemy. Hierbij is de attack() methode van de Boss een override van die van de Enemy. Hierbij heb je veel code herhaald (de Boss doet hetzelfde als de Enemy, maar heeft een kans op het gebruik van zijn shield) Verbeter je code door bij deze attack() methode alle dubbele code bij de Boss versie weg te halen en deze te vervangen door een aanroep van de attack van zijn parent (de Enemy). Zorg wel dat de Boss zijn shield kan blijven gebruiken natuurlijk. b: De Boss class erft de init () method van Enemy(). We willen nu ook de waarde van de shield variabele van de Boss kunnen instellen bij het maken van een Boss object. Override de init () methode van Enemy(). Roep in de nieuwe init () van Boss de originele init () van de Enemy aan en voeg het instellen van de shield variabele toe. 11

2.7 MEERVOUDIGE OVERERVING Bij overerving ben je niet beperkt tot 1 parent class. Een nieuwe klasse kan variabelen en functies erven van meerdere klassen tegelijk. Een voorbeeld zie je in het volgende filmpje: Thenewboston tutorial 33: Multiple inheritance Hierin zie je: - Het erven van functies uit 2 verschillende classes Een aantal dingen komen nog niet naar voren in het eenvoudige voorbeeld van het filmpje. Multiple inheritance is in sommige gevallen zeker handig, maar kan ook voor nieuwe problemen zorgen. Opdracht 8: Ga verder met de code uit opdracht 7. In het spel willen we het mogelijk maken dat er verschillende dingen tijdelijk onzichtbaar kunnen worden. Niet alle Enemies kunnen het, dus het kan geen eigenschap van de Enemy class zijn. Eindbazen kunnen het wel, dus je zou het als eigenschap van de eindbaas kunnen toevoegen. Maar er zijn ook items die het kunnen (al hebben we die nog niet geïmplementeerd). Om te voorkomen dat we code dubbel moeten schrijven, kiezen we voor de volgende oplossing: Schrijf een nieuwe class Invisible(). Deze class introduceert een class-variabele visible die de waarde True krijgt. De class heeft ook 2 methoden: make_visible() en make_invisible(). Deze methoden passen de waarde van de visible variabele aan in respectievelijk True en False. Zorg nu dat je Boss class ook een kind is van de Invisible class (en nog steeds van Enemy natuurlijk) en test of je een instantie van Boss zichtbaar en onzichtbaar kunt maken. 2.7.1 MULTIPLE INHERITANCE PROBLEEM 1: CONFLICTERENDE METHODEN Bij meervoudige overerving kunnen gemakkelijk conflicten ontstaan. Bekijk het volgende voorbeeldje: class Papa: def zeg_hallo(self): print "Hallo!" class Mama: def zeg_hallo(self): print "Hoi!" class Kind(Papa, Mama): def slaap(self): print "Zzzz" 12

henkie = Kind() henkie.zeg_hallo() Hier erft de Kind klasse dezelfde methode van 2 verschillende ouder klassen. Wat zou de uitvoer zijn bij de laatste regel? Het goede antwoord is Hallo!. Bij een conflict zoals hier, worden de parent classes op volgorde bekeken. Omdat de Kind klasse hier als eerste van de Papa class erft (die staat als eerste in zijn lijstje), zal daarvan de zeg_hallo() methode worden overgenomen. Je kunt je voorstellen dat dit voor problemen of verwarring kan zorgen. 2.7.2 MULTIPLE INHERITANCE PROBLEEM 2: MEERDERE INIT () METHODEN Het probleem van conflicterende methoden van de vorige paragraaf wordt nog erger als beide ouders een init () methode hebben. Immers maar 1 van deze init () methoden wordt overgenomen door de kindklasse. Hierdoor kunnen zelfs verkeerd ingestelde variabelen ontstaan in de kindklasse. De init () methodes van beide ouders waren er immers niet voor niets. Ze zetten allerlei startwaarden goed en dat gebeurt nu misschien niet meer. Een manier om dit (deels) te omzeilen is om de Kindklasse een nieuwe init () methode te geven die de init () methoden van beide ouders eerst aanroept. Bijvoorbeeld: class Kind(Papa, Mama): def init (self, var1, var2, var3): Papa. init (self, var1) Mama. init (self, var2) self.nieuwe_waarde = var3 Dit is geen garantie tot succes, want misschien spreken de init () functies van de Papa en Mama classes elkaar wel tegen en krijg je dus nog steeds rare dingen In de praktijk wordt multiple inheritance niet veel gebruikt omdat het (zoals hierboven kort besproken) regelmatig meer problemen introduceert dan het oplost. In sommige specifieke gevallen is het nuttig en het is goed te weten dat het kan, maar wees er voorzichtig mee 13

3 ERROR HANDLING 3.1 INLEIDING PROGRAMMING TODAY IS A RACE BETWEEN SOFTWARE ENGINEERS STRIVING TO BUILD BIGGER AND BETTER IDIOT- PROOF PROGRAMS, AND THE UNIVERSE TRYING TO PRODUCE BIGGER AND BETTER IDIOTS. SO FAR, THE UNIVERSE IS WINNING. - RICK COOK Gebruikers doen niet altijd wat je verwacht (en eerlijk is eerlijk: als programmeur is het ook niet altijd te overzien op welke manieren je code gebruikt gaat worden, die maken ook fouten), dus de kans dat er tijdens de uitvoering van een programma wel eens een fout optreedt is groot. Dit is op zichzelf geen ramp, als er maar op een goede manier mee wordt omgegaan in de code. Een programma dat er halverwege mee ophoudt met een of andere obscure error die de gebruiker niet snapt is altijd een slechte zaak. De oplossing: Error handling Het basisprincipe van error handling is eigenlijk vrij eenvoudig: - Je moet erop verdacht zijn welke delen van je code tot fouten kunnen leiden bij (verkeerd) gebruik. - Aan deze delen voeg je een speciale pythonconstructie toe die de fouten vangt. - Bij het vangen van een fout, schrijf je code die voorkomt dat het programma crasht op de fout. - Eventueel voorzie de je de gebruiker van nuttige feedback (duidelijke foutmelding) zodat deze actie kan ondernemen. 14

3.2 SOORTEN FOUTMELDINGEN Laten we eerst maar eens wat dingen expres mis laten lopen om een beetje een gevoel te krijgen wat er zoal stuk kan gaan. Opdracht 9: Voer de volgende opdrachten uit en noteer wat de foutmelding is. Probeer ook te begrijpen wat de foutmelding zegt en leg uit wat er precies mis gaat. a. Voer de volgende code uit. Wat gaat er mis en waarom? lijst = [1, 2, 3] print lijst[6] b. Voer de volgende code uit. Geef verschillende getallen als invoer. Probeer dan ook eens het getal 0 als invoer. Wat gaat er mis en waarom? deler = int(raw_input("met hoeveel personen ga je een taart delen? ")) stuk = 1.0 / deler print "Dan krijgt iedereen", stuk, "stuk taart" c. Voer de code uit vraag b nog eens uit, maar in plaats van een getal voer je een stuk tekst in zoals appeltaart. Wat gaat er mis en waarom? d. Voer de volgende code uit. Voer verschillende getallen in. Het werkt niet, waarom? (kijk goed naar de foutmelding): getal = raw_input("geef een getal: ") uitkomst = 2 + getal print "De uitkomst is:", uitkomst e. Leg uit wat er mis gaat bij het maken van het nieuwe object mijntaart: class Appeltaart: calorieen = 2500 def init (self, aantal_stukken): self.stukken = aantal_stukken mijntaart = Appeltaart() Je hebt nu een aantal foutmeldingen uitgeprobeerd. Er zijn er nog (heel) veel meer (kijk voor de grap maar eens naar de hele lijst). Dat python onderscheid maakt tussen zoveel verschillende foutmeldingen is een goede zaak. Zoals we gaan zien kun je fouten vangen en afhandelen. Hierbij kun je verschillende soorten fouten op een verschillende manier behandelen en voor elke fout de juiste oplossing inbouwen. 15

3.3 EXCEPTIONS Ìn de vorige paragraaf heb je (expres) een aantal fouten veroorzaakt. Het optreden van zo n fout heet in Python een Exception (uitzondering). Deze exceptions kun je vangen en zorgen dat ze op een nette manier worden afgehandeld in plaats van met een cryptische foutmelding en een onderbroken programma. Bekijk het volgende filmpje: Thenewboston tutorial 28: Exceptions Hierin leer je: - Try block - Catch blok met specifieke Exceptions - Catch blok met algemene Exceptions - Finally block Opdracht 10: Ga verder met je code van opdracht 8. a. Breid de constructor ( init () ) van Enemy uit, zodat de Enemy (en de Boss dankzij overerving ook) een naam krijgt. Dit is simpelweg een string variabele die in de class wordt opgeslagen. b. We gaan nu de gebruiker bij je code betrekken (oei, weten we dat zeker?). Laat de gebruiker een gevecht organiseren tussen 2 Enemies/Bosses. Hiervoor ga je de gebruiker steeds keuzes aanbieden. Bijvoorbeeld: Wat is deelnemer 1? Kies 1 voor Enemy en 2 voor Boss Wat is de naam van deelnemer 1? Op deze manier bepaalt de gebruiker alle eigenschappen van de 2 deelnemers. Deze laat je tegen elkaar vechten zoals voorheen en drukt steeds de tussenstand van het gevecht af. Gebruik ook de naam van de deelnemers bij het afdrukken van de informatie De gebruiker kan natuurlijk allerlei fouten maken. Zorg dat je met loops en try except blokken alle fouten netjes vangt, zodat de gebruiker je programma niet meer stuk kan maken. 16

4 PO: TEXT-BASED RPG 4.1 INLEIDING In deze praktische opdracht gaan we de opgedane kennis van de voorgaande hoofdstukken naar een flink hoger niveau tillen. We gaan een zogenaamde text-based RPG maken in OO python. Dat is een soort rollen/avonturenspel, maar zonder graphics. Niet omdat graphics niet mogelijk zijn (we zouden immers weer met Pygame aan de slag kunnen gaan), maar omdat je zonder je druk te hoeven maken over de graphics, meer focus kunt leggen op de logische (objectgeoriënteerde) opbouw van je code en je sneller toekomt aan uitbreidingen voor je game. We gaan slim gebruik maken van object oriëntatie om de opzet van onze code logisch en efficiënt te maken. Wt heeft een tutorialserie voor deze PO op youtube gemaakt. Hierbij wordt de code van een basisversie van de RPG game stap voor stap opgebouwd. Het volgen van deze tutorial levert je goed inzicht in hoe je een groter project goed kunt structureren volgens OO principes. Doordat je de code zelf mee maakt met de filmpjes, heb je daarna goede kennis van de code en de logica erachter en dat maakt het eenvoudiger om op een goede manier je eigen uitbreidingen toe te voegen. 4.2 GROEPJES Omdat OO programmeren samenwerking goed ondersteunt (objecten kunnen relatief makkelijk los van elkaar geprogrammeerd worden), mag deze PO met zijn tweeën worden uitgevoerd, maar alleen werken mag ook. Belangrijk als je met zijn tweeën werkt: Je wordt beiden geacht de tutorialfilmpjes te volgen en afzonderlijk van elkaar de basiscode te bouwen, omdat dit het noodzakelijke inzicht in de code verschaft die je beiden nodig zult hebben. Bij de uitbreidingen werk je samen verder en kun je natuurlijk taken en code verdelen. Daarnaast maak je in je verslag duidelijk hoe de taakverdeling was en dat je de objectstructuur hebt gebruikt om het samenwerken aan de code te bevorderen. 4.3 AANPAK Je voert de volgende stappen uit: (2 pnt) Je bekijkt de tutorialserie van Wt op youtube en bouwt deze basisversie van de game na (7 pnt) Je bedenkt zelf toffe uitbreidingen op deze basisgame en implementeert deze uitbreidingen. (Tips en suggesties staan verderop) (1 pnt) Je schrijft een verslag met een toelichting op je code: o Beschrijf de regels/toevoegingen die je hebt gedaan (wat is er nieuw t.o.v. de basisgame) o Licht de structuur van je code toe. Hoe heb je de uitbreidingen gebouwd? o Korte evaluatie o Voor tweetallen: Wat was de taakverdeling en hoe heb je OO technieken gebruikt om het werk goed te verdelen o Logboekje met bestede tijd (per persoon) 17

4.4 BEOORDELING Bij de beoordeling wordt (onder andere) op het volgende gelet: - Complexiteit van de uitbreidingen. o Niet elke uitbreiding is even ingewikkeld, de complexiteit speelt een rol in de waarde ervan. - Kwaliteit van je code o Goed gebruik gemaakt van OO: extra objecten toegevoegd waar nodig, logische variabelen en methoden in je klassen, zo min mogelijk dubbel gemaakte code, etc. o Commentaar. Licht hier en daar in je code een stukje toe, dat maakt het een stuk leesbaarder. o Logische naamgeving, structuur en commentaar. Bij een groot project is leesbaarheid van je code extra belangrijk. Geef alles logische namen, voorzie je code van commentaar en houd het zo overzichtelijk mogelijk. - Creativiteit o Je hebt veel ruimte voor eigen inbreng. Toffe ideeën en goede uitwerkingen ervan worden beloond. - Kwaliteit van het verslag o Bevat het de vereiste onderdelen en in voldoende detail o Leesbaarheid en opmaak. Het oog wil ook wat, maak er een net document van. De deadline van dit project is zondag 28 oktober. Voor elke week te laat, wordt 1 punt afgetrokken. Deze tijd wordt naar boven afgerond op weken. Dus bijvoorbeeld: - 1 dag te laat = 1 punt aftrek (1 week) - 4 dagen te laat = 1 punt aftrek (1 week) - 7 dagen te laat = 1 punt aftrek (1 week) - 8 dagen te laat = 2 punten aftrek (2 weken) - etc. 4.5 TIPS VOOR UITBREIDINGEN Zomaar wat suggesties van Wt voor uitbreidingen. Gameplay uitbreidingen: Meer monsters (subclasses van Monster) o Andere eigenschappen (damage, hitpoints, etc.) o Speciale vardigheden (speler bevriezen, andere monsters genezen, etc.) o Eindbaas die echt moeilijk te verslaan is Meer items (subclasses van Item) o Drankjes (Jezelf genezen, tijdelijke voordelen, etc...) o Meerdere kledingstukken (helmen, ringen, etc. Met elk nuttige eigenschappen natuurlijk) Geld en winkel o Monsters zijn ook goud waard en daarvoor kun je soms dingen kopen in een shop (items, potions etc.) 18

Speciale aanvallen (mogelijkheid meerdere monsters tegelijk aan te vallen, schakel tijdelijk een monster uit, etc..) Toverspreuken met interessante effecten Meer eigenschappen voor de speler die invloed hebben op de acties in de game (stat points, toverkracht, etc.) Spelertypes (Je kunt kiezen uit een boogschutter of zwaardvechter of... Elk met eigen voor- en nadelen) Minigames? Bv. een puzzel oplossen voor een bonus. Of speel yahtzee/galgje/hogerlager/... met een monster in plaats van hem te bevechten. Meer helden tegelijk. Misschien bestuur je wel een gropeje helden met verschillende eigenschappen in plaats van maar 1 player... Technische uitbreidingen: Opslaan van je voortgang, zodat je later verder kunt spelen. Savegames dus. (Zoek tutorials over "Serialization" of gebruik textfiles om de belangrijkste waardes van je game in op te slaan, zodat je deze weer kunt herstellen bij het laden) De "algemene code" zoals die onderaan de basisversie van de game staat, overzetten naar een "Game" class voor meer structuur Beveilig je code met error handling. We hebben de try...except behandeld in dit boekje. Gebruik dit om je code te beveiligen tegen runtime errors zoals foute invoer. Verhaal en beleving Voeg verhaalelementen toe om de speler meer in het spel te betrekken. Beschrijf de setting en de gebeurtenissen in meer detail. Ascii art. Geen graphics wil niet zeggen dat je niet toch dingen kunt "tekenen" met ascii art... Meer keuze. Naast vechten kun je je de speler ook meer beslissingen in het spel laten nemen die invloed hebben op het verhaal en/of het verloop. 19

5 LINKS EN VERVOLGSUGGESTIES Geen genoeg van Python? Er valt nog oneindig veel te leren. Zowel over mogelijkheden van de taal Python zelf als over programmeren en algoritmiek in het algemeen. Een aantal suggesties voor verdere studie (geen toetsstof uiteraard) - The Hitchhikers guide to Python Onofficiele handleiding over alles wat met Python te maken heeft. Van installatie tot goede programmeerstijlen - Thenewboston youtube tutorials Een aantal filmpjes stonden gelinkt in dit boekje. De hele playlist is nuttig (let op: wel Python 3, maar de verschillen met Python 2 zijn klein) - Learn Python the hard way Goed praktisch leerboek over Python 20