Na dit hoofdstuk snap je:
- wat
selfprecies is (en waarom het nodig is), - wat
__init__doet (en wat het níet is), - hoe method calls “onder water” werken,
- hoe je omgaat met default values,
- en de grootste valkuil: mutable defaults.
1. Wat is self? #
self is simpel gezegd: het object waar je op werkt.
Als je dit doet:
alice.greet()Pythondan betekent dat eigenlijk:
User.greet(alice)PythonDus: self is gewoon de eerste parameter van een instance-methode, en Python vult die automatisch in met het object (de instance).
Voorbeeld ter illustratie
class User:
def greet(self):
return f"Hi, ik ben {self}"
alice = User()
print(alice.greet())
print(User.greet(alice))PythonBeide calls doen hetzelfde. De tweede vorm maakt zichtbaar wat er gebeurt.
Waarom heet het self?
Conventie. Je kán het anders noemen, maar doe het niet: iedereen verwacht self.
2. Waarom is self nodig? #
Omdat een methode meestal iets moet kunnen:
- lezen uit het object (
self.name) - schrijven naar het object (
self.balance += 10) - of andere methodes op hetzelfde object aanroepen (
self.reset())
Zonder self weet de methode niet welke instance hij moet aanpassen.
3. Wat doet __init__? #
__init__ is de methode die Python automatisch aanroept direct nadat een object is aangemaakt.
__init__zet meestal de begin-state (attributen) klaar.__init__maakt het object niet; dat doet__new__(geavanceerder, vaak niet nodig).
Praktisch onthouden:
__init__= initialiseren van de instance
Voorbeeld:
class User:
def __init__(self, name):
self.name = name
alice = User("Alice")Python4. Hoe werkt __init__ met parameters? #
Positional & keyword arguments #
class User:
def __init__(self, name, is_admin=False):
self.name = name
self.is_admin = is_admin
User("Alice")
User("Bob", True)
User(name="Carol", is_admin=True)PythonDefault values zijn supernormaal
Default parameters maken je class makkelijker te gebruiken.
5. Meerdere manieren om te initialiseren (Pythonic opties) #
Soms wil je “alternate constructors”, zoals:
- user maken vanuit JSON
- user maken vanuit een email
In Python doe je dat vaak met class methods:
class User:
def __init__(self, name):
self.name = name
@classmethod
def from_email(cls, email):
name = email.split("@")[0]
return cls(name)
u = User.from_email("alice@example.com")
print(u.name) # alicePythonDit is later handig bij “net” ontwerpen.
6. De grootste valkuil: mutable default arguments #
Het probleem #
Dit ziet er onschuldig uit, maar is een bug-magneet:
class Team:
def __init__(self, members=[]):
self.members = membersPythonWaarom fout?
- Die lege lijst
[]wordt één keer gemaakt bij het definiëren van de functie. - En daarna gedeeld door alle instances die de default gebruiken.
Gevolg:
t1 = Team()
t2 = Team()
t1.members.append("Alice")
print(t2.members) # ['Alice'] 😬PythonDe juiste oplossing #
Gebruik None en maak dan binnenin een nieuwe lijst:
class Team:
def __init__(self, members=None):
self.members = [] if members is None else list(members)PythonNu krijgt elk object zijn eigen lijst.
Regel om te onthouden:
Gebruik geen [], {}, set() als default argument in __init__ (of in functies). Gebruik None.
7. Wanneer zet je validatie in __init__? #
Als je object anders “ongeldig” kan bestaan.
Voorbeeld:
class Product:
def __init__(self, name, price):
if price < 0:
raise ValueError("Price cannot be negative")
self.name = name
self.price = pricePythonVuistregel: als een regel altijd waar moet zijn (invariant), bewaak hem in __init__ of via properties/methodes.
Samenvatting (kort) #
self= de instance waar je mee werkt; Python vult hem automatisch in bijobj.method().__init__= init van state; geen object-creator (dat is__new__).- Default args zijn top, maar vermijd mutable defaults → gebruik
None.

