Programmeren is een kunst. En net als bij kunst, is het belangrijk om de beste kwasten en verf te kiezen, om het mooiste resultaat te krijgen. Object-Oriented Programming met Python is een vaardigheid die je nodig hebt om een kunstwerk te kunnen maken.

Het kiezen van de juiste programmeertaal voor je project is essentieel, en kan een soepel lopend project betekent, of een absolute nachtmerrie. Daarom moet je altijd de ideale taal vinden die perfect bij je use case past.

Dat is dan ook de voornaamste reden om object-oriented programming in Python te leren, wat overigens ook één van de meest populaire programmeertalen is.

Tijd om te gaan leren dus!

Een voorbeeld van een Python programma

Voordat we de diepte in gaan, eerst een vraag: heb je wel eens een Python programma geschreven zoals het voorbeeld hieronder?

secret_number = 20
 
while True:
   number = input('Guess the number: ')
 
   try:
       number = int(number)
   except:
       print('Sorry that is not a number')
       continue
 
   if number != secret_number:
       if number > secret_number:
           print(number, 'is greater than the secret number')
 
       elif number < secret_number:
           print(number, 'is less than the secret number')
   else:
       print('You guessed the number:', secret_number)
       break

Dit is de code van een eenvoudig programma waarmee je een getal kan raden. Kopieer het maar naar een Python bestand en voer het uit op je computer. Het zal meteen en soepel werken.

Maar nu een probleem: wat als we je vragen om een nieuwe feature toe te voegen aan het programma? Dit kan iets simpels zijn, bijvoorbeeld:

“Als de input een veelvoud is van het geheime getal, geef de gebruiker dan een hint.”

Het programma zal snel veel complexer worden naarmate je het aantal features vergroot, en het aantal geneste voorwaarden zal moeilijk te beheren zijn.

En dat is precies het probleem dat object-oriented programming op kan lossen.

Vereisten om Python OOP te leren

Voordat we in object-oriented programming duiken, raden we sterk aan dat je al een goede basis hebt in Python.

Wat precies een “basis” is, is natuurlijk lastig te definiëren. Daarom hebben we een cheat sheet gemaakt met alle belangrijkste concepten die je moet kennen om aan de slag te kunnen met object-oriented programming in Python.

  • Variabele: Symbolische naam die naar een specifiek object verwijst (gedurende dit artikel zullen we leren wat objecten zijn).
  • Rekenkundige operators: Optelling (+), aftrekking (-), vermenigvuldiging(*), delen(/), geheeltallig-delen(//), modulo (%).
  • Ingebouwde data-types: Numeriek (integers, floats, complex), verzamelingen (strings, lists, tuples), Boolean (True, False), dictionaries, en sets.
  • Booleaanse uitdrukkingen: Uitdrukking waarvan het resultaat True of False
  • Voorwaardelijk: Evalueert een Booleaanse uitdrukking en voert een proces uit op basis van het resultaat. Wordt geregeld via if/else
  • Loop: Ook wel lussen, zijn herhalende uitvoering van stukken code. Dit kunnen for of while loops zijn.
  • Functies: Blokken georganiseerde en herbruikbare code. Je kan ze via het keyword def
  • Argumenten: Objecten die je aan een functie doorgeeft. Bijvoorbeeld: sum([1, 2, 4])
  • Uitvoeren van een Python script: Open een terminal of command line en typ “python <bestandsnaam>.”
  • Open een Python Shell: Open een terminal en typ python of python3, afhankelijk van je systeem.

Nu je deze concepten helder hebt, kunnen we doorgaan met het leren van object-oriented programming.

Wat is object-oriented programming in Python?

Object-oriented programming (OOP) is een paradigma of methode voor programmeren waarbij we complexe problemen benaderen als objecten.

Een methode of paradigma is een theorie die de basis biedt voor het oplossen van problemen.

Wanneer we het dus hebben over OOP, hebben we het over een verzameling concepten en patronen waarbij we problemen oplossen via objecten.

Een object in Python is een verzameling data (attributes) en gedrag (methods). Je kan objecten zien zoals veel tastbare dingen om je heen. Denk bijvoorbeeld aan een rekenmachine:

Een rekenmachine kan een object zijn.
Een rekenmachine kan een object zijn.

Zoals je wellicht ziet zijn de data (attributen) altijd zelfstandige naamwoorden, en het gedrag (methode) wordt altijd beschreven door werkwoorden.

Dit onderscheid is een centraal concept voor object-oriented programming. Je kan objecten bouwen waarin je data opslaat en die bepaalde functionaliteit bevatten.

Waarom gebruiken we object-oriented programming in Python?

Met OOP kan je veilige en robuuste software bouwen. Veel Python frameworks en libraries gebruiken dit paradigma om hun codebase te bouwen. Voorbeeld zijn Django, Kivy, pandas, NumPy, en TensorFlow.

We kijken naar de belangrijkste voordelen van het gebruik van OOP in Python.

Voordelen van OOP in Python

De volgende redenen zijn uitstekende argumenten om te kiezen voor object-oriented programming in Python.

Alle moderne programmeertalen gebruiken OOP

Dit paradigma is onafhankelijk van de programmeertaal. Als je OOP in Python leert, zul je het ook kunnen toepassen op de volgende talen:

Al deze talen zijn van zichzelf object-oriented of bieden mogelijkheden voor object-oriented functionaliteit. Wil je na Python meer over die talen leren, dan is het dus makkelijker, omdat je veel overeenkomsten zult zien tussen verschillende programmeertalen die met objecten werken.

Met OOP kan je sneller programmeren

Sneller programmeren betekent niet altijd minder regels code schrijven. Het betekent dat je meer features in minder tijd kan implementeren, zonder de stabiliteit in gevaar brengt.

Object-oriented programming maakt het mogelijk om code te hergebruiken door het implementeren van abstractie. Dit principe maakt je code beter te lezen en bondiger.

Zoals je wellicht weet, zijn programmeurs veel meer tijd kwijt aan het lezen van code dan aan het schrijven ervan. Dat is de reden dat leesbaarheid veel belangrijker is dan het zo snel mogelijk afmaken van features.

Productiviteit neemt af bij slecht leesbare code
Productiviteit neemt af bij slecht leesbare code

Je zal verderop meer lezen over het principe van abstractie.

OOP helpt je om spaghetti-code te voorkomen

Herinner je je programma om getallen te raden van de inleiding van dit artikel?

Als je features blijft toevoegen, heb je op een gegeven moment allemaal geneste if statements. Deze wirwar van code noemen we spaghetti-code, en dat moet je natuurlijk voorkomen.

OOP geeft de mogelijkheid om alle logica te comprimeren in objecten, waardoor je allerlei geneste if statements kan voorkomen.

OOP verbetert je analyse en begrip van de situatie

Nadat je wat meer ervaring hebt met OOP, zul je sneller problemen kunnen onderscheiden in kleine en specifieke objecten.

Hierdoor kan je sneller aan de slag met nieuwe projecten.

Gestructureerd programmeren en object-oriented programming

Gestructureerd programmeren is het meestgebruikte paradigma voor beginners, omdat het de eenvoudigste manier is om een klein programma te bouwen.

Hierbij voer je een Python programma in volgorde uit. Je geeft de computer dus een lijst met taken die van boven naar beneden uitgevoerd worden.

Laten we eens kijken naar zo’n voorbeeld bij een programma voor een koffiebar.

small = 2
regular = 5
big = 6
 
user_budget = input('What is your budget? ')
 
try:
   user_budget = int(user_budget)
except:
   print('Please enter a number')
   exit()
 
if user_budget > 0:
   if user_budget >= big:
       print('You can afford the big coffee')
       if user_budget == big:
           print('It\'s complete')
       else:
           print('Your change is', user_budget - big)
   elif user_budget == regular:
       print('You can afford the regular coffee')
       print('It\'s complete')
   elif user_budget >= small:
       print('You can buy the small coffee')
       if user_budget == small:
           print('It\'s complete')
       else:
           print('Your change is', user_budget - small)

Bovenstaande code werkt als de verkoper van een koffiebar. Je wordt gevraagd naar je budget, en wordt dan de grootst mogelijke koffie aangeboden die je kan betalen.

Probeer het maar eens uit te voeren in de terminal. Het zal stap voor stap uitgevoerd worden, op basis van je input.

De code werkt perfect, maar er zitten drie nadelen aan:

  1. Er zit veel herhalende logica in.
  2. Er worden veel geneste if voorwaarden gebruikt.
  3. Het is moeilijk te lezen en te bewerken.

OOP is bedacht als oplossing voor al deze problemen.

Laten we eens naar bovenstaand programma kijken, maar dan met OOP. Maak je geen zorgen als je het niet meteen begrijpt. We willen vooral het verschil tussen object-oriented programming en gestructureerd programmeren laten zien.

class Coffee:
        # Constructor
        def __init__(self, name, price):
                self.name = name
                self.price = float(price)
        def check_budget(self, budget):
                # Check if the budget is valid
                if not isinstance(budget, (int, float)):
                        print('Enter float or int')
                        exit()
                if budget < 0: 
                    print('Sorry you don\'t have money') 
                    exit() 
        def get_change(self, budget):
                return budget - self.price
        
        def sell(self, budget):
                self.check_budget(budget)
                if budget >= self.price:
                        print(f'You can buy the {self.name} coffee')
                        if budget == self.price:
                                print('It\'s complete')
                        else:
                                print(f'Here is your change {self.get_change(budget)}$')

                        exit('Thanks for your transaction')

Opmerking: Alle volgende concepten worden verderop uitgelegd.

De code hierboven definieert een class met de naam “Coffee”. Die class heeft twee attributen: “name” en “price”, die allebei gebruikt worden in de methoden. De primaire methode is “sell”, waarin alle logica voor het verkoopproces uitgevoerd wordt.

Als je die class probeert uit te voeren, krijg je echter geen output. Dat komt omdat we alleen het “template” voor de koffie bepalen, en niet de soorten koffie zelf.

Die class kunnen we implementeren met de volgende code:

small = Coffee('Small', 2)
regular = Coffee('Regular', 5)
big = Coffee('Big', 6)
 
try:
   user_budget = float(input('What is your budget? '))
except ValueError:
   exit('Please enter a number')
  
for coffee in [big, regular, small]:
   coffee.sell(user_budget)

In dit deel maken we instances, oftewel koffie-objecten, van de class “Coffee”, en gebruiken dan de “sell” methode van elke coffee, totdat de gebruiker aankomt bij een koffie die betaalbaar is.

We krijgen met beide aanpakken dezelfde output, maar met OOP kunnen we het programma veel makkelijker uitbreiden.

Hieronder een tabel met een vergelijking van object-oriented programming en gestructureerd programmeren:

OOP Gestructureerd programmeren
Eenvoudiger te onderhouden Moeilijk te onderhouden
Don’t Repeat Yourself (DRY) aanpak Code wordt vaak herhaald
Kleine stukjes code worden veel hergebruikt Erg veel code
Object aanpak Blokken code
Eenvoudiger te debuggen Moeilijker te debuggen
Steile leercurve Minder steile leercurve
Gebruikt in grote projecten Geoptimaliseerd voor simpele programma’s

Om de vergelijking samen te vatten:

  • Geen van beide aanpakken is perfect, want OOP kan juist te veel van het goede zijn in kleinere projecten.
  • Er zijn niet maar twee manieren om een probleem op te lossen, er zijn nog allerlei andere.
  • OOP wordt vooral gebruikt in projecten met veel code, terwijl gestructureerd programmeren ideaal is voor simpelere projecten.

Tijd om door te gaan naar ingebouwde objecten in Python.

In Python is alles een object

We verklappen je een geheimpje: je gebruikt al de hele tijd OOP.

Zelfs bij andere paradigma’s in Python, zul je nog objecten gebruiken voor allerlei dingen.

Dat komt omdat binnen Python, alles een object is.

De definitie van een object was immers: Een object in Python is een verzameling data (attributes) en gedrag (methods).

Dat komt overeen met elke soort data in Python.

Een string is een verzameling data (characters) met gedrag (upper(), lower(), etc.). Hetzelfde geldt voor integers, floats, booleans, lists, en dictionaries.

Voordat we verder gaan, kijken we nog eens naar de betekenis van attributes en methods.

Attributes en methods

Attributes zijn interne variabelen binnen objecten, en methods zijn functies die bepaald gedrag produceren.

Een eenvoudige oefening binnen de Python shell. Je kan deze openen door python of python3 in te typen in je terminal.

Python 3.9  shell
Python shell

Laten we de methods en types ontdekken met de Python shell

>>> kinsta = 'Kinsta, Premium Application, Database, and Managed WordPress hosting'
>>> kinsta.upper()
'KINSTA, PREMIUM APPLICATION, DATABASE, AND MANAGED WORDPRESS HOSTING'

In de tweede regel gebruiken we een string method, upper(). Hiermee krijg je de inhoud van een string terug in hoofdletters (uppercase). Maar de originele variabele blijft hetzelfde.

>>> kinsta
'Kinsta, Premium Application, Database, and Managed WordPress hosting'

We kijken naar de functies bij het werken met objecten.

De functie type() geeft je het type van een object. Het “type” is de class waartoe een object hoort.

>>> type(kinsta)
# class 'str'

De dir() functie geeft alle attributes en methods van een object. We testen dit bij de variabele kinsta.

>>> dir(kinsta)
['__add__', '__class__',  ........... 'upper', 'zfill']

Nu proberen we enkele van de verborgen attributes van dit object te zien.

 >>> kinsta.__class__ # class ‘str’ e>

Hiermee krijg je de class van het object kinsta te zien. Het enige dat de functie type geeft is dus het __class__ attribute van een object.

Je kan via de terminal experimenten met de verschillende data types, om te zien welke attributes en methods erbij horen. Je kan ook meer lezen over de ingebouwde data types in de officiële documentatie.

Je eerst object in Python

Een class is een soort template. Hiermee kan je custom objecten maken op basis van de attributes en methoden die je zelf definieert.

Je kan het zien als een koekjesvorm waarmee je de perfecte koekjes kan bakken (dan bedoelen we natuurlijk de objecten, geen tracking cookies), met bepaalde eigenschappen zoals vorm en grootte.

Aan de andere kant hebben we instances. Een instance is een individueel object van een class, met een uniek geheugenadres.

Instances in Python
Instances in Python

Nu je weet wat instances en classes zijn, kunnen we die eens gaan uitproberen.

Om een class in Python te definiëren, gebruik je het class keyword, en vervolgens de gewenste naam. In dit geval maak je een class met de naam Cookie.

Opmerking: In Python gebruiken we de camel case naamconventie voor de namen van classes.

class Cookie:
	pass

Open je Python shell en typ bovenstaande code in. Om een instance van een class te maken, kan je gewoon de naam intypen, met haakjes erachter. Hetzelfde proces gebruiken we om een functie te maken.

cookie1 = Cookie()

Gefeliciteerd! Je bent nu de trotse bezitter van je eerste object in Python! Je kan het id en type bekijken met deze code:

id(cookie1)
140130610977040 # Unique identifier of the object

type(cookie1)
<class '__main__.Cookie'>

Zoals je kan zien heeft het object nu een unieke identifier in het geheugen, en is het type Cookie.

Je kan ook controleren of een object een instance is van een class, met de functie isinstance().

isinstance(cookie1, Cookie)
# True
isinstance(cookie1, int)
# False
isinstance('a string', Cookie)
# False

Constructor method

De __init__() method wordt ook wel “constructor” genoemd. Het wordt elke keer gebruikt in Python wanneer een een object oproepen.

De constructor maakt de initiële staat van een object, met het minimum aan parameters. Laten we de Cookie class aanpassen, zodat de class parameters accepteert in de constructor.

class Cookie:
	# Constructor
	def __init__(self, name, shape, chips='Chocolate'):
		# Instance attributes
		self.name = name
		self.shape = shape
		self.chips = chips

In de class Cookie moet elk cookie nu een naam(name), vorm (shape) en vulling (chips) hebben. Die laatste hebben we gedefinieerd als “Chocolate”.

Aan de andere kant refereert self naar de instance van de class (het object zelf).

Probeer de class maar eens uit in de shell, en maak een instance van een cookie aan.

cookie2 = Cookie()
# TypeError

Je krijgt nu een foutmelding. Dat komt omdat je de minimale hoeveelheid data moet bieden voor het object, in dit geval dus de name en shape, aangezien we chips al standaard op “Chocolate” hebben ingesteld.

cookie2 = Cookie('Awesome cookie', 'Star')

Om de attributes van een instance te openen, moet je de puntnotatie gebruiken.

cookie2.name
# 'Awesome cookie'
cookie2.shape
# 'Star'
cookie2.chips
# 'Chocolate'

Tot zover is de Cookie class nog niet heel spannend. Laten we een method bake() toevoegen om het wat interessanter te maken.

class Cookie:
	# Constructor
	def __init__(self, name, shape, chips='Chocolate'):
		# Instance attributes
		self.name = name
		self.shape = shape
		self.chips = chips

	# The object is passing itself as a parameter
	def bake(self):
		print(f'This {self.name}, is being baked with the shape {self.shape} and chips of {self.chips}')
		print('Enjoy your cookie!')

Om een method te callen gebruik je de puntnotatie, en roep je dit op als een function.

cookie3 = Cookie('Baked cookie', 'Tree')
cookie3.bake()
# This Baked cookie, is being baked with the shape Tree and chips of Chocolate
Enjoy your cookie!

De 4 pijlers van OOP in Python

Object-oriented programming bestaat uit vier belangrijke pijlers:

1. Abstractie

Abstractie verbergt de interne functie van een toepassing voor de gebruiker. De gebruiker kan zowel de eindgebruiker zijn als andere developers.

We komen abstractie overal tegen. Zo weet je bijvoorbeeld hoe je je smartphone moet gebruiken, maar waarschijnlijk weet je niet precies wat er allemaal gebeurt wanneer je een app opent.

Een ander voorbeeld is Python zelf. Je weet hoe je het kan gebruiken via functionele software, en dat kan je ook doen als je Python’s interne werking niet precies kent.

Door ditzelfde principe toe te passen op code, kan je alle objecten in een probleem verzamelen en de standaard functionaliteit naar classes abstraheren.

2. Overerving (inheritance)

Door overerving kunnen we diverse subclasses definiëren, van een eerder gedefinieerde class.

Het belangrijkste doel hierbij is om het DRY principe te volgen. Je kan een hoop code hergebruiken door de gedeelde componenten te implementeren via superclasses.

Je kan dit vergelijken met het biologische principe van genetische overerving. Kinderen (subclasses) zijn het resultaat van overerving van twee ouders (superclasses). Ze erven de fysieke eigenschappen (attributes) en een deel van het gedeelde gedrag (methods).

3. Aanpassing (polymorphism)

Door aanpassing kunnen we methods en attributes van subclasses net wat anders maken dan in de superclass.

Letterlijk betekent polymorfisme “veelvormigheid“. Dat is omdat we methodes bouwen met dezelfde naam maar verschillende functies.

Om terug te gaan naar de erfelijkheid, zijn kinderen ook een goed voorbeeld van polymorfisme. Ze kunnen een bepaalde gedrag, get_hungry() erven, maar met een kleine aanpassing, bijvoorbeeld doordat ze elke 4 uur honger krijgen in plaats van elke 6 uur.

4. Inkapseling

Inkapseling is het proces waarbij we de interne integriteit van data binnen een class beschermen.

Alhoewel er geen private statement bestaat in Python, kan je inkapseling toepassen door mangling te gebruiken in Python. Er zijn speciale methods genaamd getters en setters waarmee we unieke attributes en methods kunnen maken.

Stel dat we een Human class maken met een uniek attribuut genaamd _height. Je kan dit attribuut alleen aanpassen binnen bepaalde beperkingen (het is menselijk nagenoeg onmogelijk om langer dan 3 meter te zijn).

Bouwen van een rekenmachine voor het berekenen van de oppervlakte van een vorm

Het mooie aan Python is dat we er allerlei software mee kunnen maken, van een Command Line Interface (CLI) programma, tot een complexe web app.

Nu je de belangrijkste concepten van OOP hebt geleerd, is het tijd om ze eens toe te passen op een echt project.

Opmerking: Alle onderstaande code is beschikbaar in dit GitHub repository. Een code beoordelingstool waarmee we versies van code kunnen beheren via Git.

Je opdracht is om een oppervlakte-rekenmachine te maken voor de volgende vormen:

  • Vierkant
  • Rechthoek
  • Driehoek
  • Cirkel
  • Zeshoek

Base class Shape (vorm)

Eerst maak je een bestand met de naam calculator.py, wat je opent in Python. Aangezien we al objecten hebben om mee te werken, kunnen we ze makkelijk abstraheren naar een class.

Je kan de overeenkomsten analyseren en realiseren dat het allemaal 2D vormen zijn. Daarom kan je het beste een class Shape maken met een method get_area(), waar elke vorm van kan erven.

Opmerking: Alle methods moeten werkwoorden zijn, volgens de afspraken. Daarom heet de method get_area() en niet gewoon area().

class Shape:
	def __init__(self):
		pass

	def get_area(self):
		pass

De bovenstaande code definieert de class, maar is zelf nog niet zo interessant.

We implementeren de functionaliteit voor de meeste vormen.

class Shape:
	def __init__(self, side1, side2):
		self.side1 = side1
		self.side2 = side2

	def get_area(self):
		return self.side1 * self.side2

	def __str__(self):
		return f'The area of this {self.__class__.__name__} is: {self.get_area()}'

Laten we stap voor stap langslopen wat deze code doet:

  • In de __init__ method, vragen we twee parameters, side1 en side2. Dit blijven instance attributes.
  • De functie get_area() geeft dan de oppervlakte van de vorm. In dit geval wordt de formule voor een rechthoek gebruikt, aangezien dat de makkelijkste optie is.
  • De __str__() method is een “magic method” net als __init__(). Hiermee kan je veranderen wat een instance print.
  • Het verborgen attribute __class__.__name__ refereert aan de naam van de class. Als je werkt met een Triangle class, zou dat attribute dus “Triangle” zijn.

Rectangle Class

Aangezien we de formule voor de oppervlakte van een rechthoek gebruiken, kunnen we een eenvoudige Rectangle class maken die niks doet, behalve overerven van de Shape class.

Om overerving in Python te gebruiken, maak je een class aan, met de superclass waarvan je wil erven in haakjes.

# Folded base class
class Shape: ...
 
class Rectangle(Shape): # Superclass in Parenthesis
	pass

Square Class

We kunnen polymorfisme gebruiken met de Square class.

Uiteindelijk is een vierkant gewoon een rechthoek waarbij alle vier de zijden gelijk zijn. We kunnen dus dezelfde wiskundige formule gebruiken voor de oppervlakte.

We doen dit door de method init aan te passen, waarbij we een side als parameter aannemen, en die doorgeven aan de constructor van de Rectangle class.

# Folded classes
class Shape: ...
class Rectangle(Shape): ...
 
class Square(Rectangle):
	def __init__(self, side):
		super().__init__(side, side)

Zoals je kan zien geeft de super function de side parameter nu twee keer door naar de superclass. Anders gezegd wordt side nu als zowel side1 als side2 doorgegeven aan de constructor.

Triangle Class

Een driehoek is half zo groot als de rechthoek eromheen.

De relatie tussen driehoeken en rechthoeken (Afbeelding: Varsity tutors).
De relatie tussen driehoeken en rechthoeken (Afbeelding: Varsity tutors).

Daarom kunnen we weer erven van de Rectangle class en de get_area method gebruiken om de driehoeksformule toe te passen, wat de helft is van de basis keer de hoogte.

# Folded classes
class Shape: ...
class Rectangle(Shape): ...
class Square(Rectangle): ...
 
class Triangle(Rectangle):
	def __init__(self, base, height):
		super().__init__(base, height)
 
	def get_area(self):
		area = super().get_area()
		return area / 2

Een andere use case van de super() function is om een method te roepen die je in de superclass gedefinieerd hebt en het resultaat als een variabele op te slaan. Dat is wat er gebeurt in de get_area() method.

Circle Class

Je kan de oppervlakte van een cirkel berekenen met de formule πr², waar r de straal van een cirkel is. Dit betekent dat we get_area() weer moeten aanpassen voor die formule.

Opmerking: We kunnen de waarde van π bij benadering gebruiken vanuit de rekenmodule.

# Folded classes
class Shape: ...
class Rectangle(Shape): ...
class Square(Rectangle): ...
class Triangle(Rectangle): …
 
# At the start of the file
from math import pi
 
class Circle(Shape):
	def __init__(self, radius):
		self.radius = radius
 
	def get_area(self):
		return pi * (self.radius ** 2)

Bovenstaande code definieert de class Circle, met een andere constructor en de get_area methods.

Alhoewel Circle erft van de Shape class, kan je elke method en attribuut naar wens opnieuw definiëren

Regular Hexagon Class

We hebben alleen de lengte van één kant van een gelijkmatige zeshoek nodig om de oppervlakte te berekenen. Het lijkt dus op de Square class, waarbij we maar één argument aan de constructor geven.

Formule voor de oppervlakte van een zeshoek(Afbeelding: BYJU’S)
Formule voor de oppervlakte van een zeshoek (Afbeelding: BYJU’S)

Maar de gebruikte formule is wel nogal anders, en gebruikt een wortel. Daarom heb je de functie sqrt() (vierkantswortel) nodig uit de rekenmodule.

# Folded classes
class Shape: ...
class Rectangle(Shape): ...
class Square(Rectangle): ...
class Triangle(Rectangle): …
class Circle(Shape): …
 
# Import square root
from math import sqrt
 
class Hexagon(Rectangle):
	
	def get_area(self):
		return (3 * sqrt(3) * self.side1 ** 2) / 2

Testen van de classes

Je kan een interactieve modus activeren bij het uitvoeren van een Python bestand via een debugger. De makkelijkste manier om dit te doen is via de ingebouwde breakpoint function.

Opmerking Deze functie is beschikbaar vanaf Python 3.7.

from math import pi, sqrt
# Folded classes
class Shape: ...
class Rectangle(Shape): ...
class Square(Rectangle): ...
class Triangle(Rectangle): …
class Circle(Shape): …
class Hexagon(Rectangle): …
 
breakpoint()

Nu kan je het Python bestand uitvoeren en experimenteren met de gemaakte classes.

$ python calculator.py
 
(Pdb) rec = Rectangle(1, 2)(Pdb) print(rec)
The area of this Rectangle is: 2
(Pdb) sqr = Square(4)
(Pdb) print(sqr)
The area of this Square is: 16
(Pdb) tri = Triangle(2, 3)
(Pdb) print(tri)
The area of this Triangle is: 3.0
(Pdb) cir = Circle(4)
(Pdb) print(cir)
The area of this Circle is: 50.26548245743669
(Pdb) hex = Hexagon(3)
(Pdb) print(hex)
The area of this Hexagon is: 23.382685902179844

Challenge

Maak een class met de method run waarbij de gebruiker een vorm kan kiezen en de bijbehorende oppervlakte kan berekenen.

Wanneer je de uitdaging afgerond hebt, kan je een pull request sturen via de GitHub repo of je oplossing hieronder in de reacties zetten.

Samenvatting

Object-oriented programming is een paradigma waarbij we problemen oplossen door ze te zien als objects. Als je Python OOP begrijpt, kan je dit ook eenvoudig toepassen op programmeertalen zoals Java, PHP, Javascript, en C#.

In dit artikel heb je geleerd over:

  • Het concept object-oriented in relatie tot Python
  • Voordelen van object-oriented programming ten opzichte van gestructureerd programmeren
  • Basis van object-oriented programming in Python
  • Concept van classes en hoe je die in Python kan gebruiken
  • De constructor van een class in Python
  • Methods en attributes in Python
  • De vier pijlers van OOP
  • Implementeren van abstractie, overerving, en polymorfisme binnen een project

Nu is het aan jou!

Als je deze gids leuk vond, bekijk dan onze post over Python tutorials.

Plaats je oplossing voor de challenge hieronder in de reacties! En kijk ook eens naar onze vergelijking tussen Python en PHP.

Daniel Diaz

Daniel is a self-taught Python Developer, Technical Writer, and long-life learner. He enjoys creating software from scratch and explaining this process through stunning articles. Follow him on Twitter: @DaniDiazTech