Skip to content
Programmeren in Python, leer de nieuwste technieken
Programmeren in PythonProgrammeren in Python
  • Home
  • Blog
  • Documentatie
  • Cursussen
Programmeren in PythonProgrammeren in Python
  • Home
  • Blog
  • Documentatie
  • Cursussen

Introductie

4
  • 1.1 Wat is Python?
  • 1.2 Python installatie
  • 1.2.1 Python installeren voor MacOS
  • 1.3 PyCharm Installatie

Basisprogrammering

6
  • 2.1 Python Basis: Variabelen, Datatypes en Operatoren
  • 2.2 Python if else (en elif)
  • 2.3 Python list (Array, Lijsten)
  • 2.4 Python Lussen: for loop, while loop, break, continue
  • 2.5 Python Functies: Definities, Parameters en Terugkeerwaarden
  • 2.6 Foutafhandeling: try, except, else, finally

Datatypes

13
  • 3.1 Introductie tot Geavanceerde Datatypes
  • 3.2 Python Tuple
  • 3.3 Python Set
  • 3.4 Python Dictionary
  • 3.5 Werken met Strings en String-methoden
  • 3.6 Collections Module: Krachtige Tools in Python
  • 3.7 Iterators en Generators
  • 3.8 List Comprehensions
  • 3.9 Geavanceerde Sortering
  • 3.10 Werken met Multi-dimensionale Data
  • 3.11 Typing en Datatypes
  • 3.12 Itertools voor Geavanceerde Iteraties
  • 3.13 Data Conversies

Modules

8
  • 4.1 Wat zijn Modules en Waarom zijn ze Belangrijk?
  • 4.2 Werken met Ingebouwde Modules
  • 4.3 Installeren en Gebruiken van Externe Pakketten
  • 4.4 Eigen Modules Maken
  • 4.5 Introductie tot Pakketten
  • 4.6 Importeren en Namespaces Begrijpen
  • 4.7 Geavanceerd: Relatief Importeren
  • 4.8 Organiseren van Grotere Projecten

Data Analyse

3
  • 5.1 Python Dataframe en Data Opschonen met Pandas
  • 5.2 Python Pandas Basisstatistieken en Data-analyse
  • 5.3 Python Numpy (NpArray): De Kracht van Numerieke Berekeningen

Webontwikkeling

5
  • 7.1 Inleiding tot Webontwikkeling
  • 7.2 HTTP-Verzoeken met requests: Communiceren met het Web
  • 7.3 Webscraping met BeautifulSoup: Data van het Web Halen als er geen APIs zijn
  • 7.4 Python Flask, een webserver & API tutorial
  • 7.5 WSGI & WebOb

Deploy

1
  • Deploy met Supervisor op Ubuntu

Object Georiënteerd Programmeren

8
  • Wat is Objectgeoriënteerd Programmeren (OOP) in Python?
  • Python class & object maken
  • self en __init__ uitgelegd (met voorbeelden)
  • Attributen afschermen: @property (getters/setters)
  • Overerving in Python + super() (en wanneer je het beter níet doet)
  • Dunder methods: __str__, __repr__, vergelijken (en waarom dit je OOP-code “Pythonic” maakt)
  • @dataclass: snelle nette classes (minder boilerplate, meer duidelijkheid)
  • OOP in de praktijk: design & structuur
View Categories
  • Home
  • Documentatie
  • Object Georiënteerd Programmeren
  • Attributen afschermen: @property (getters/setters)

Attributen afschermen: @property (getters/setters)

4 minuten leestijd

Na dit hoofdstuk kun je:

  • attributen “Pythonic” afschermen met @property,
  • validatie toevoegen zonder dat je API verandert,
  • read-only en computed properties maken,
  • en je kent de valkuilen (recursie, te veel magie, verkeerde plek voor logica).

1) Waarom @property in Python? #

In veel talen maak je expliciet getters/setters: get_name(), set_name(...) om een variabele op te halen of weg te schrijven.
In Python wil je meestal dat gebruikers gewoon:

user.name
Python

kunnen doen.

Maar soms wil je óók:

  • validatie (geen negatieve leeftijd),
  • read-only gedrag,
  • computed values,
  • of later intern refactoren zonder code van gebruikers te breken.

Daar is @property perfect voor.

2. Basis: van “open attribuut” naar property #

Zonder property (simpel maar geen controle) #
class Product:
    def __init__(self, price):
        self.price = price
Python

Probleem: price kan negatief gezet worden:

p = Product(10)
p.price = -999  # geen blokkade
Python

Met property (controle + zelfde gebruik) #
class Product:
    def __init__(self, price):
        self.price = price  # gaat via de setter

    @property
    def price(self):
        return self._price

    @price.setter
    def price(self, value):
        if value < 0:
            raise ValueError("Price cannot be negative")
        self._price = value
Python

Als je Product(10) doet, dan voert __init__ uit:

  • self.price = price
    Dat is niet “zet het attribuut direct”, maar: Python ziet dat price een property is → en roept dus price.setter aan.

Dus initialisatie gebruikt dezelfde regels als later aanpassen. Dat is handig.

Gebruik blijft hetzelfde:

p = Product(10)
p.price = 12
print(p.price)
Python

En hierdoor worden dus de getter en setters aangeroepen, waardoor je bij het ophalen of wegschrijven specifieke acties (code) kan toevoegen.

Waarom niet direct self._price = price?

Dat kan ook, maar dan bypass je je eigen validatie:

def __init__(self, price):
    self._price = price  # slaat setter over
Python

Gevolg: Product(-5) zou dan gewoon kunnen bestaan, terwijl je setter dat eigenlijk wil verbieden.

Dus let op: intern gebruiken we _price als “private-ish” opslag.

_price is een conventie voor “intern gebruik” #

In Python kun je niet echt een veld echt privé maken zoals in sommige andere talen. Daarom gebruiken Python-programmeurs een naamconventie:

  • price = de publieke interface (wat andere code “mag” gebruiken)
  • _price = intern attribuut (“gebruik dit liever niet direct van buitenaf”)

De underscore _ betekent dus: dit is bedoeld voor intern gebruik binnen de class (of module). Het is geen harde beveiliging, maar een duidelijke afspraak.

Is _price echt privé?

Niet echt, je kunt dit nog steeds doen:

p = Product(10)
p._price = -999  # kan, maar is “not recommended”
Python

Het punt is: je hoort het niet te doen. Als je het tóch doet, omzeil je bewust de regels/validatie.

En hoe zit het met “echte private” in Python?

Er is ook __price (dubbele underscore). Dat triggert name mangling (Python hernoemt het intern), waardoor het lastiger is om van buitenaf te gebruiken. Maar:

  • het is nog steeds niet “security”,
  • en vaak onnodig zwaar voor gewone code.

Meestal is _price de beste balans: duidelijk, simpel, Pythonic.

Als je wil kan ik ook een klein voorbeeld geven van __price (name mangling) en wanneer dat nuttig is.

3. Read-only properties #

Soms wil je iets wel kunnen lezen, maar niet zomaar overschrijven.

Bijvoorbeeld: een id die eenmaal gezet is.

class User:
    def __init__(self, user_id, name):
        self._id = user_id
        self.name = name

    @property
    def id(self):
        return self._id
Python

Nu kan:

u = User(123, "Alice")
print(u.id)   # 123
u.id = 999    # AttributeError: can't set attribute
Python

Dat is precies wat je wil: de buitenwereld kan het niet kapot maken.

4. Computed properties (afgeleid van andere data) #

Properties zijn top voor waarden die je niet opslaat, maar berekent.

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    @property
    def area(self):
        return self.width * self.height
Python

Gebruik:

r = Rectangle(3, 4)
print(r.area)  # 12
Python

Voordeel: je hoeft area niet “bij te houden” wanneer width/height veranderen.

5. Validatie + invarianten netjes afdwingen #

Voorbeelden van regels die objecten vaak moeten bewaken:

  • leeftijd ≥ 0
  • percentage tussen 0 en 1
  • status is één van een set
  • string mag niet leeg zijn
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if value < 0:
            raise ValueError("Age cannot be negative")
        self._age = value
Python

6. Veelgemaakte property-fouten #

Fout 1: oneindige recursie (klassieker) #

Dit gaat mis:

class Product:
    @property
    def price(self):
        return self.price  # ❌ roept zichzelf weer aan
Python

goed:

return self._price
Python

Fout 2: setter die zichzelf aanroept #
@price.setter
def price(self, value):
    self.price = value  # ❌ oneindige loop
Python

Goed:

self._price = value
Python

Fout 3: te veel logica in properties
Een property hoort meestal: #
  • iets te lezen,
  • licht te valideren,
  • of iets af te leiden.

Maar: een property die zware I/O doet (API call, database query) is vaak verwarrend:

user.profile  # en ineens een netwerkrequest?!
Python

Beter: expliciete methode load_profile() of fetch_profile().

7. Wanneer gebruik je géén @property? #

  • Als een attribuut simpel is en geen regels nodig heeft → laat het open.
  • Als je eigenlijk een actie uitvoert → maak een methode.
    • account.balance (property) ✅
    • account.withdraw(50) (methode) ✅
    • account.balance = account.balance - 50 (outside) ❌ (breekt encapsulation)

Nu je getters en setters hebt geleerd is het belangrijk dat je het concept van overerving snapt om goed object georiënteerd te kunnen programmeren.

Updated on januari 4, 2026

What are your Feelings

self en __init__ uitgelegd (met voorbeelden)Overerving in Python + super() (en wanneer je het beter níet doet)
Inhoudsopgave
  • 1) Waarom @property in Python?
  • 2. Basis: van “open attribuut” naar property
    • Zonder property (simpel maar geen controle)
    • Met property (controle + zelfde gebruik)
      • _price is een conventie voor “intern gebruik”
  • 3. Read-only properties
  • 4. Computed properties (afgeleid van andere data)
  • 5. Validatie + invarianten netjes afdwingen
  • 6. Veelgemaakte property-fouten
    • Fout 1: oneindige recursie (klassieker)
    • Fout 2: setter die zichzelf aanroept
    • Fout 3: te veel logica in propertiesEen property hoort meestal:
  • 7. Wanneer gebruik je géén @property?
Programmeren in Python

Leer python op je eigen tempo met mooie interactieve hedendaagse voorbeelden.

© Copyright 2026 Programmeren in Python.
Sign inSign up

Sign in

Don’t have an account? Sign up
Lost your password?

Sign up

Already have an account? Sign in