Ga naar hoofdinhoud

Kennismaking met Python magic methods

Ontdek wat magic methods zijn en bekijk het verschil tussen methods en functions.
Bijgewerkt 2 okt 2026  · 11 min lezen

Verken met AI

ChatGPTClaudePerplexity

Een van de factoren die Python zo krachtig maakt, zijn magic methods. In sommige Pythonista-kringen hoor je ze ook wel ‘dunder methods’ noemen, vanwege de dubbele underscores. 

Hun rol in Python is het uitvoeren van zogeheten ‘operator overloading’, wat simpelweg betekent dat een vooraf gedefinieerde operator een uitgebreide betekenis krijgt. Met andere woorden: met operator overloading voeg je aangepaste gedragingen toe aan je classes zodat je ze kunt gebruiken met Python-operators en ingebouwde functionaliteit.  

In dit artikel duiken we dieper in Python magic methods door: 

  • Het verschil tussen methods en functions te onderscheiden 
  • Uit te leggen wat magic methods zijn
  • Een paar Python-voorbeelden te geven. 

Bekijk deze DataLab-werkmap om mee te volgen met de code uit deze tutorial. 

Python-methods vs. functions

Voordat we kunnen ingaan op wat magic methods zijn, moeten we eerst het verschil begrijpen tussen een method en een function in Python. 

Python gebruikt methods om het gedrag van een object weer te geven. Methods zijn dus gekoppeld aan een object en voeren bewerkingen uit op de data binnen een object. Een ander onderscheidend kenmerk van een method is de parameter self, die altijd als eerste parameter aan de method wordt doorgegeven. 

Let op: het hoeft niet letterlijk het woord self te zijn als eerste parameter, maar onder Pythonistas is algemeen aanvaard dat dit best practice is. 

# Example of a method
class Human:
    # This is a method
    def walk(self):
        print("I am walking") 

Methods zijn afhankelijk van de class waarmee ze zijn geassocieerd. Om een method aan te roepen, moet er dus eerst een instantie van de class worden gemaakt voordat je de method met de punt-operator kunt benaderen. 

# This will work
joe = Human()
joe.walk()

"""
I am walking
"""




# This will throw a NameError
walk()

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/tmp/ipykernel_153/2327344440.py in <module>
      4
      5 # This will throw a NameError
----> 6 walk()

NameError: name 'walk' is not defined

Een function daarentegen is anders: we hoeven geen instantie van een class te maken. 

Python-functions zijn stappen die als een blok code worden uitgevoerd wanneer ze worden aangeroepen. Ze worden onafhankelijk van een class-object gedefinieerd, wat betekent dat je ze rechtstreeks bij naam kunt aanroepen. Omdat ze niet aan een class zijn gekoppeld, hoeven we self niet als parameter door te geven – parameters zijn optioneel. 

In wezen is een function gewoon een set goed gedefinieerde instructies die de interpreter gebruikt om een taak uit te voeren. 

# Example of a function
def run():
  print("I am running.")
​
run()

"""
I am running.
"""

Zoals we hebben besproken in ons artikel How to call and write functions, zijn er twee soorten functions: ingebouwde en door de gebruiker gedefinieerde. 

  • Built-in functions: Functions die zijn opgenomen in de Python-standaardbibliotheek. 
  • User-defined functions: Functions die door de gebruiker zijn gedefinieerd - Python staat toe dat gebruikers hun eigen functions definiëren en gebruiken die in een Python-programma kunnen worden aangeroepen.  

In veel opzichten zijn methods en functions identiek - ze worden bijvoorbeeld allebei met een def-statement gedefinieerd. Het fundamentele verschil is dat methods gekoppeld zijn aan een object en worden gebruikt om te werken op de data binnen een class, terwijl functions onafhankelijk worden gedefinieerd en overal in een programma bij naam kunnen worden aangeroepen. 

Wat zijn Python magic methods?

Aan het begin van de tutorial noemden we dat magic methods ook wel dunder methods worden genoemd vanwege de dubbele underscores. Daarmee bedoelen we dat alle Python magic methods beginnen en eindigen met twee underscores. 

De bekendste magic method is de __init__-methode, die het mogelijk maakt om een class te initialiseren met specifieke attributen. 

class Employee:
    def __init__(self, name, age, role):
        self.name = name
        self.age = age
        self.role = role

Om een instantie van deze class te maken, moeten we de attributen name, age en role opgeven. Bijvoorbeeld:

user_1 = Employee(name="John", age=24, role="Data Scientist")

Als je dat niet doet, krijg je een TypeError. 

De __init__-methode valt onder de categorie initialisatie- en constructiemagic methods, maar het is er slechts één van velen. De onderstaande tabel bevat enkele andere magic methods voor initialisatie en constructie. 

__new__(cls, other)

Wordt gebruikt om een nieuwe instantie van een class te maken

__init__(self, other)

Wordt aangeroepen nadat een nieuwe instantie is gemaakt; alle attributen die aan de classconstructor worden doorgegeven, worden als attributen gebruikt. 

__del__(self)

Ook wel de destructor; wordt aangeroepen wanneer een instantie wordt vernietigd. 

De eenvoudigste manier om magic methods te begrijpen, is als een contract tussen je implementatie en de Python-interpreter. Een van de voorwaarden in dat contract schrijft voor dat Python onder de motorkap bepaalde acties uitvoert in een gegeven situatie, zoals het initialiseren van een classinstantie met specifieke objecten. 

Met andere woorden: het is niet jouw verantwoordelijkheid om een magic method rechtstreeks aan te roepen – Python doet dat voor je achter de schermen. 

Stringrepresentatiemethoden

Python is een objectgeoriënteerde programmeertaal (OOP) – alles in Python is een object. Wanneer een nieuw object wordt gemaakt, creëren we impliciet een gerelateerd object, omdat alle classes erven van object.  

Let op: je kunt de overerving ook expliciet maken door de class object aan je class door te geven. 

# This works
class Car:
  pass
​
# This also works
class Vehicle(object):
  pass
​
car = Car()
vehicle = Vehicle()
​
print(car, vehicle, sep="\n")

"""
<__main__.Car object at 0x7f80449dc0a0>
<__main__.Vehicle object at 0x7f80449dc1f0>
"""

In de code hierboven hebben we twee lege classes gemaakt, maar de Python-interpreter wist nog steeds wat hij moest afdrukken toen we print aanriepen. Dit is mogelijk omdat alle classes erven van de object-class (de ouder van alle classes in Python), en die heeft een magic method __repr__, die door de print-functie wordt aangeroepen om een waarde terug te geven aan ons hoofdprogramma.  

Wie bekend is met overerving, weet dat een kindclass zijn ouderclass kan overschrijven door een eigen method met dezelfde naam te definiëren. 

# Overriding the object __repr__
class Vehicle:
  def __repr__(self):
      return f"{self.__class__.__qualname__}"
​
vehicle = Vehicle()
print(vehicle)

"""
Vehicle
"""

Je kunt ook de magic method __str__ gebruiken om een stringrepresentatie te maken die door print wordt aangeroepen. 

Sterker nog, de magic method __repr__ fungeert als vangnet voor de magic method __str__. Wanneer we dus print aanroepen, zoekt Python eerst naar de in je class gedefinieerde __str__-methode en valt anders terug op de __repr__-methode. 

# Using __str__ for string representation
class Vehicle:
  def __str__(self):
      return f"{self.__class__.__qualname__}"
     
vehicle = Vehicle()
print(vehicle)

"""
Vehicle
"""

De onderstaande tabel bevat een lijst met andere magic methods voor stringrepresentatie. 

__str__(self)

Wordt aangeroepen door Python’s ingebouwde str()-functie en door de print-statement om de informele stringrepresentatie van een object te tonen. Let op: dit hoeft geen geldige Python-expressie te zijn. 

__repr__(self)

Wordt aangeroepen door Python’s ingebouwde repr()-functie en stringconversies om de officiële stringrepresentatie van een object te tonen. Let op: dit zou eruit moeten zien als een geldige Python-expressie, maar als dat niet mogelijk is, heeft een string met een nuttige beschrijving de voorkeur. 

__unicode__(self)

Wordt aangeroepen om Python’s ingebouwde unicode()-functie te implementeren en retourneert een Unicode-object. 

__hash__(self)

Wordt aangeroepen door Python’s ingebouwde hash()-functie en bij operaties op leden van gehashte collecties. De methode moet een geheel getal retourneren. 

__nonzero__(self)

Wordt aangeroepen door Python’s ingebouwde bool()-operatie om truth value testing te implementeren. De methode moet True of False (of hun gehele-equivalent 1 of 0) retourneren. 

Encapsulation- “magic”-methods 

Encapsulation is een van de basisconcepten in objectgeoriënteerd programmeren (OOP). Het verwijst naar het bundelen van data met de methods die op die data werken, of het beperken van directe toegang tot bepaalde componenten binnen een object.

Ontwikkelaars uit andere OOP-talen bekritiseren regelmatig dat Python encapsulation in classes niet echt omarmt. Zij zijn gewend aan expliciete modifiers voor methods of velden waarmee ze zaken als private attributen met public getters en setters kunnen definiëren. Het verschil in Python is dat veel van de bestaande encapsulation via magic methods verloopt. 

Zo is __setattr__ een encapsulation-oplossing die ons in staat stelt gedrag te definiëren voor toekenning aan een attribuut, ongeacht of het al bestaat. Met andere woorden: je kunt regels definiëren voor wijzigingen in de waarden van attributen. 

import string

class Alphabet():
    def __setattr__(self, name, value):
        self.__dict__[name] = value.upper()

a = Alphabet()

# Assinging an attribute that does not exist
# The setattr should convert it to caps despite being set as lowercase
a.alphabet = string.ascii_lowercase
print(a.alphabet)

In de bovenstaande code hebben we een class Alphabet gemaakt zonder attributen, maar we hebben Python verteld dat we elk attribuut van de classinstantie dat we zetten, willen kapitaliseren.

We begrijpen dat OOP voor sommige lezers wat ver kan aanvoelen. Wil je je OOP-kennis in Python bijspijkeren, bekijk dan de Python Programmer Track van DataCamp.   

Wiskundige magic methods

Een andere categorie Python magic methods zijn de wiskundige magic methods (ook wel normale rekenkundige operatoren). Expressies worden in Python gemaakt met speciale symbolen die we ‘operators’ noemen. Het gebruik van zulke operators in een expressie houdt in dat je objecten maakt met wiskundige magic methods. Als je je daar niet aan houdt, krijg je een TypeError. 

class Numbers:
  def __init__(self, a, b):
      self.a = a
      self.b = b
   
set_a = Numbers(2, 4)
set_b = Numbers(3, 5)
​
print(set_a + set_b)
"""
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_152/3639634723.py in <module>
      7 set_b = Numbers(3, 5)
      8
----> 9 print(set_a + set_b)

TypeError: unsupported operand type(s) for +: 'Numbers' and 'Numbers'
"""

In de code hierboven probeerden we meerdere instanties van de class Numbers bij elkaar op te tellen, wat zoals verwacht een fout opleverde. Een oplossing zou zijn om in onze class een method te maken om getallen op te tellen, maar dat zou ons verhinderen om expressies te maken. 

Een betere oplossing is om een __add__-magic method te implementeren, als volgt:  

# Using add operator
class Numbers:
    def __init__(self, a, b):
        self.a = a
        self.b = b
   
    def __add__(self, other):
        # Only permit Numbers objects to be added
        if not isinstance(other, Numbers):
            return NotImplemented
        return Numbers(other.a + self.a, other.b + self.b)
   
    def __repr__(self):
      return f"{self.__class__.__qualname__}({self.a}, {self.b})"
   
a = Numbers(2, 4)
b = Numbers(3, 5)
print(a + b) # Should result in Numbers(5, 9)


"""
RandomNumbers(5, 9)
"""

Het bovenstaande codevoorbeeld stelt ons alleen in staat twee Numbers-objecten op te tellen. Laten we nog een wiskundige magic method implementeren die ons toestaat een Numbers-object met een geheel getal te vermenigvuldigen. 

# Multiplying Numbers with an integer
class Numbers:
    def __init__(self, a, b):
        self.a = a
        self.b = b
   
    def __add__(self, other):
        # Only permit Numbers objects to be added
        if not isinstance(other, Numbers):
            return NotImplemented
        return Numbers(other.a + self.a, other.b + self.b)
   
    def __mul__(self, other):
      if not isinstance(other, int):
          return NotImplemented
         
      return Numbers(self.a * other, self.b * other)
   
    def __repr__(self):
      return f"{self.__class__.__qualname__}({self.a}, {self.b})"
   
a = Numbers(2, 4)
print(a * 5) # Should return 10, 20




"""
RandomNumbers(10, 20)
"""

In de code hierboven hebben we een __mul__-magic method toegevoegd zodat we de getallen van onze custom class met een geheel getal kunnen vermenigvuldigen. 

Merk op dat het Numbers-object aan de linkerkant van de *-operator staat – dat is niet toevallig. Laten we het aan de rechterkant van de operator zetten en kijken wat er gebeurt. 

- snip --

a = Numbers(2, 4)
print(3 * a)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_152/2857655049.py in <module>
      1 a = Numbers(2, 4)
----> 2 print(3 * a)

TypeError: unsupported operand type(s) for *: 'int' and 'Numbers'

Python geeft een TypeError. 

De door ons geïmplementeerde __mul__-magic method houdt alleen rekening met het geval waarin het Numbers-object aan de linkerkant van de *-operator staat. Om deze functionaliteit uit te breiden, moeten we de reverse-magic method __rmul__ toevoegen. 

# Enabling reverse multiplication
class Numbers:
    def __init__(self, a, b):
        self.a = a
        self.b = b
   
    def __add__(self, other):
        # Only permit Numbers objects to be added
        if not isinstance(other, Numbers):
            return NotImplemented
        return Numbers(other.a + self.a, other.b + self.b)
   
    def __mul__(self, other):
      if not isinstance(other, int):
          return NotImplemented
      return Numbers(self.a * other, self.b * other)

    def __rmul__(self, other):
        return self.__mul__(other)
   
    def __repr__(self):
      return f"{self.__class__.__qualname__}({self.a}, {self.b})"
   
a = Numbers(2, 4)
print(5 * a) # Should return 10, 20

"""
Numbers(10, 20)
"""

Nu kunnen we een vermenigvuldigingsuitdrukking maken zonder te hoeven letten op welke kant van de operator het Numbers-object staat. 

Afsluiting

Het basisprincipe voor het benutten van Python magic methods blijft hetzelfde: maak een class en overschrijf de magic methods van de object-class. Er zijn zó veel magic methods in Python dat dit een extreem lange tutorial zou worden als we ze allemaal afzonderlijk zouden behandelen. We raden je sterk aan de Python-documentatie te bekijken om een idee te krijgen van de volledige reikwijdte van Python magic methods die je kunt gebruiken om je Python-programmeervaardigheden te verbeteren.  



Onderwerpen
Python

Cursussen voor Python

Cursus

Python voor gemiddeld niveau

4 uur
1.4M
Maak je data science skills sterker: creëer visualisaties met Matplotlib en bewerk DataFrames met pandas.
Bekijk detailsRight Arrow
Start Cursus
Meer bekijkenRight Arrow
Gerelateerd

blog

AI vanaf nul leren in 2026: een complete gids van de experts

Ontdek alles wat je moet weten om in 2026 AI te leren, van tips om te beginnen tot handige resources en inzichten van industrie-experts.
Adel Nehme's photo

Adel Nehme

15 min

Meer BekijkenMeer Bekijken