In objectgeoriënteerd programmeren (OOP), een aanpak voor softwareontwerp, gebruiken we “objecten” om entiteiten uit de echte wereld te modelleren. Een object is een datastructuur met attributen (data) en methoden (functies) die op die data werken. Complexe systemen kunnen makkelijker te ontwerpen zijn met objecten.
Encapsulatie is een fundamenteel concept in OOP. Het betekent dat je de data en de methoden van een object groepeert en de details verbergt voor de buitenwereld. Zie encapsulatie als een proces dat een ‘capsule’ (een object) creëert met zijn eigen data en manieren om die te manipuleren.
Het belangrijkste doel van encapsulatie is om:
Rechtstreekse toegang tot de data te voorkomen (dataintegriteit).
Het systeem te vereenvoudigen door alleen te tonen wat nodig is (abstractie).
Privémethoden zijn cruciaal om deze encapsulatie te bereiken door de interne implementatiedetails van een klasse te verbergen.
Door een methode privé te maken, laat je andere programmeurs weten dat deze methode niet bedoeld is om direct te worden aangeroepen. Dit kan bugs en fouten voorkomen door ervoor te zorgen dat de interne status van een object alleen op gecontroleerde manieren kan worden gewijzigd.
Hier introduceren we privémethoden, de syntaxis om ze te definiëren, hoe je ze implementeert met praktijkvoorbeelden en de best practices voor het gebruik ervan.
Wat zijn privémethoden?
Privémethoden in objectgeoriënteerd programmeren (OOP) zijn functies binnen een klasse die uitsluitend voor intern gebruik zijn bedoeld. Ze kapselen de functionaliteit van een klasse in, zodat de interne werking afgeschermd blijft van externe interactie.
Deze encapsulatie zorgt voor een laag van abstractie, waardoor de klasse de controle behoudt over zijn interne toestand en gedrag, en zijn implementatie kan wijzigen zonder externe code die erop vertrouwt te beïnvloeden.
In Python geef je volgens de conventie privémethoden aan door de methodenaam te laten voorafgaan door een enkele underscore (_) of dubbele underscores (__). Dit is een hint voor ontwikkelaars over de beoogde scope van de methode en is slechts een conventie.
Hoewel deze conventie geen strikte privacy afdwingt zoals in sommige andere talen, is het binnen de Python-community een gerespecteerde manier om het beoogde gebruik van de methode te signaleren. Later gaan we dieper op deze aspecten in.
De syntaxis van privémethoden
Er zijn twee verschillende manieren om privémethoden te definiëren; we bekijken ze aan de hand van voorbeelden.
We kunnen een privémethode definiëren met een enkele underscore vóór de functienaam:
classMyClass:def_private_method(self):print("This is a private method")Mogelijk gemaakt door
Deze definitie is slechts een conventie voor programmeurs, want de functie is nog steeds van buiten de klasse toegankelijk, al wordt dat niet aanbevolen.
Laten we een object maken en proberen de gemaakte privémethode te benaderen:
# Creating an object
obj = MyClass()# Accessing from outside
obj._private_method()# Not recommended to call directly, but possibleMogelijk gemaakt door
Er is nog een syntaxis voor het definiëren van privémethoden in Python met dubbele underscores. Die ziet er zo uit:
classMyClass:def__private_method(self):print("This is a private method")
obj = MyClass()# obj.__private_method() # This will raise an AttributeErrorMogelijk gemaakt door
Als we proberen de privémethode van buiten de klasse te benaderen, wordt er een AttributeError opgegooid, wat aangeeft dat deze niet rechtstreeks via de functienaam kan worden aangeroepen.
Samengevat de syntaxis van privémethoden in Python:
Enkele underscore: puur een conventie voor programmeurs, kan van buiten de functie worden benaderd.
Dubbele underscore: kan niet van buiten de functie worden benaderd met alleen de functienaam. Het is nog steeds toegankelijk via “name mangling”, wat we later in deze tutorial zullen zien.
Privémethoden in Python implementeren
Als praktijkvoorbeeld nemen we een veilige en gebruiksvriendelijke BankAccount-klasse om financiële transacties voor een gebruiker te beheren. De vereisten voor bankrekeningen zijn:
De klasse moet het saldo van de rekeninghouder inkapselen, zodat er kan worden gestort en opgenomen, terwijl wordt gewaarborgd dat het saldo niet rechtstreeks van buiten de klasse kan worden gemanipuleerd.
De klasse moet veilige overboekingen tussen rekeningen faciliteren, waarbij het saldo van de ontvangende rekening wordt bijgewerkt zonder het interne mechanisme voor saldomodificatie bloot te geven.
De oplossing moet voldoen aan de principes van objectgeoriënteerd programmeren, met name encapsulatie en abstractie, om de integriteit van de gegevens van de rekening te waarborgen en een duidelijke, eenvoudige interface te bieden voor interactie met de rekening.
Natuurlijk heeft een bankrekening meer functionaliteiten, zoals saldocontrole, valutaconversie en renteafhandeling — maar om het eenvoudig te houden, negeren we die in onze implementatie.
Laten we deze oplossing implementeren en de code begrijpen.
classBankAccount:def__init__(self, account_holder, initial_balance=0):
self.account_holder = account_holder
self.__balance = initial_balance # Private attributedefdeposit(self, amount):if amount >0:
self.__balance += amount
print(f"Deposited ${amount}. New balance: ${self.__balance}")else:print("Deposit amount must be positive.")defwithdraw(self, amount):if0< amount <= self.__balance:
self.__balance -= amount
print(f"Withdrew ${amount}. New balance: ${self.__balance}")else:print("Insufficient funds or invalid amount.")def__update_balance(self, amount):# Private method
self.__balance += amount
deftransfer(self, amount, other_account):if0< amount <= self.__balance:
self.withdraw(amount)
other_account.__update_balance(amount)print(f"Transferred ${amount} to {other_account.account_holder}.")else:print("Insufficient funds or invalid amount.")Mogelijk gemaakt door
We maken eerst een BankAccountclass die al het gewenste gedrag en de functionaliteit omvat die nodig zijn voor een BankAccount-object.
De BankAccount-klasse heeft een privé-attribuut __balance en een privémethode __update_balance:
Privévariabele (__balance): Dit is een attribuut van de BankAccount-klasse dat het huidige rekeningsaldo opslaat. Het is als privé gemarkeerd door de naam te laten voorafgaan door twee underscores (__). Dit betekent dat het alleen bedoeld is om binnen de klasse zelf te worden benaderd. Het wordt bijvoorbeeld aangepast door de methoden deposit, withdraw en __update_balance. Externe toegang tot dit attribuut wordt niet aanbevolen.
Privémethode (__update_balance): Het doel van deze methode is het bijwerken van het rekeningsaldo. Ze wordt aangeroepen door de methode transfer om tijdens een overboeking het saldo van de ontvangende rekening bij te werken. Door hier een privémethode te gebruiken, kapsel je de logica voor het bijwerken van het saldo in, zodat dit alleen kan op gecontroleerde manieren die door de klasse zijn gedefinieerd.
Voel je vrij om een nieuw Python-bestand te maken, de bovenstaande en onderstaande code te kopiëren en te plakken, en uit te voeren om het zelf te zien.
# Using the Bank Account Solution
account1 = BankAccount("John Doe",1000)
account2 = BankAccount("Jane Doe",500)
account1.deposit(200)
account1.withdraw(100)
account1.transfer(300, account2)Mogelijk gemaakt door
Je ziet dan de onderstaande output:
Deposited $200. New balance: $1200
Withdrew $100. New balance: $1100
Withdrew $300. New balance: $800
Transferred $300 to Jane Doe.Mogelijk gemaakt door
Gefeliciteerd! Je hebt je BankAccount-oplossing gemaakt met een privémethode!
Op basis van de output zien we dat bij de gebruikelijke bankhandelingen zoals storten, opnemen en overboeken, het gebruikelijke logische gedrag van een bankrekening wordt gevolgd.
De __init__-methode: is dit een privémethode?
Je hebt waarschijnlijk de methode __init__ gezien in het BankAccount-voorbeeld. Omdat deze ook dubbele underscores gebruikt, vraag je je misschien af of dit ook een privémethode is.
De methode __init__ wordt niet beschouwd als een privémethode op dezelfde manier als methoden die voor privacy met dubbele underscores worden voorafgegaan.
In plaats daarvan is het een onderdeel van speciale methoden in Python, vaak “dunder”-methoden genoemd (afkorting van “double underscore”), die een specifieke rol in de taal hebben. Andere voorbeelden van zulke speciale methoden zijn __str__, __repr__ en __del__.
Laten we begrijpen hoe deze speciale methode in ons voorbeeld is gebruikt:
classBankAccount:def__init__(self, account_holder, initial_balance=0):
self.account_holder = account_holder
self.__balance = initial_balanceMogelijk gemaakt door
Zoals we zien, is de methode __init__ de constructor voor een klasse. Deze wordt automatisch aangeroepen wanneer een nieuw exemplaar van de klasse wordt gemaakt, en wordt gebruikt om de attributen van het object te initialiseren. Voor de klasse BankAccount wordt de methode __init__ gebruikt om de beginwaarden in te stellen voor de attributen account_holder en __balance.
Geavanceerde concepten: name mangling in Python
Eerder gaven we aan dat privémethoden in Python slechts een conventie zijn en dat de Python-taal, in tegenstelling tot andere programmeertalen, privacy niet strikt afdwingt.
Dat klopt: we zagen dat privémethoden direct konden worden benaderd bij gebruik van een enkele underscore, maar dat de toegang werd beperkt bij gebruik van een dubbele underscore.
Waarom? Vanwege een concept dat “name mangling” wordt genoemd in Python.
Wanneer je een attribuutnaam laat voorafgaan door dubbele underscores, wijzigt Python de naam automatisch door een enkele underscore en de klassenaam vóór de oorspronkelijke attribuutnaam toe te voegen.
Deze gewijzigde naam is hoe het attribuut intern binnen de klasse wordt opgeslagen. Het proces van het op deze manier wijzigen van de naam staat bekend als name mangling.
Name mangling is om twee redenen nuttig:
Voorkomen van naamconflicten: Bij overerving zou een attribuut met dezelfde naam in een subklasse conflicteren met dat in de superklasse. Name mangling helpt dit te voorkomen door ervoor te zorgen dat namen uniek zijn per klasse.
Een zekere mate van privacy: Hoewel Python geen echt private attributen heeft, maakt name mangling attributen minder toegankelijk van buiten de klasse, en biedt zo een zekere mate van privacy.
Laten we een voorbeeld bekijken om dit beter te begrijpen.
classMyClass:def__init__(self):
self.__private_attribute ="I am private"def__private_method(self):print("This is a private method")
obj = MyClass()print(obj.__private_attribute)# This will raise an AttributeErrorMogelijk gemaakt door
In dit voorbeeld zijn __private_attribute en __private_method onderhevig aan name mangling. Intern worden ze respectievelijk opgeslagen als _MyClass__private_attribute en _MyClass__private_method. Pogingen om ze met hun oorspronkelijke namen van buiten de klasse te benaderen, resulteren in een AttributeError.
Je kunt ze echter nog steeds benaderen met hun gemanglede namen:
print(obj._MyClass__private_attribute)# This will print "I am private"
obj._MyClass__private_method()# This will print "This is a private method"Mogelijk gemaakt door
Hoewel name mangling attributen minder toegankelijk maakt, is het belangrijk om te benadrukken dat dit geen waterdichte manier is om privacy in Python te garanderen. Het is vooral een conventie om aan te geven dat een attribuut is bedoeld voor intern gebruik binnen de klasse.
Best practices voor het gebruik van privémethoden en -variabelen
Privémethoden en -variabelen effectief inzetten vraagt om het volgen van bepaalde best practices. Deze zorgen ervoor dat je code niet alleen functioneel is, maar ook duidelijk, onderhoudbaar en veilig.
Hier zijn enkele best practices om te volgen:
Gebruik een enkele underscore voor “beschermde” attributen. Als je wilt aangeven dat een attribuut of methode bedoeld is voor gebruik binnen de klasse en zijn subklassen, maar niet voor extern gebruik, laat je deze voorafgaan door een enkele underscore (_). Dit is een conventie in Python die andere ontwikkelaars signaleert dat het attribuut of de methode “beschermd” is en niet direct moet worden benaderd.
Gebruik dubbele underscore voor “privé” attributen. Als je een attribuut of methode minder toegankelijk wilt maken van buiten de klasse om toevallige wijziging of gebruik te vermijden, laat je deze voorafgaan door een dubbele underscore (__). Dit triggert name mangling en maakt het lastiger (maar niet onmogelijk) om het attribuut of de methode van buiten de klasse te benaderen.
Gebruik privémethoden voor interne logica. Privémethoden (die met een enkele of dubbele underscore) zijn een goede manier om de interne logica van je klasse in te kapselen. Gebruik ze voor taken die specifiek zijn voor de implementatie van de klasse en niet moeten worden blootgesteld als onderdeel van de publieke interface.
Tot slot is het belangrijk om consistent te zijn met je codeerconventies. Houd je aan de naamgevingsconventies en gebruik ze consequent in je codebase. Dit maakt je code begrijpelijker en onderhoudbaarder voor andere ontwikkelaars én voor je toekomstige zelf.
Conclusie
In deze tutorial heb je kennisgemaakt met de concepten achter privémethoden, hun syntaxis en wanneer je ze kunt gebruiken. We hebben ook meerdere voorbeelden gezien die illustreren hoe je ze in je volgende codeerproject kunt toepassen. Tot slot hebben we enkele best practices bekeken om in gedachten te houden bij het gebruik ervan.
Als senior data scientist ontwerp, ontwikkel en implementeer ik grootschalige machinelearningsoplossingen om bedrijven te helpen betere, datagedreven beslissingen te nemen. Als schrijver over data science deel ik inzichten, carrièreadvies en diepgaande, praktijkgerichte tutorials.
In objectgeoriënteerd programmeren (OOP), een aanpak voor softwareontwerp, gebruiken we “objecten” om entiteiten uit de echte wereld te modelleren. Een object is een datastructuur met attributen (data) en methoden (functies) die op die data werken. Complexe systemen kunnen makkelijker te ontwerpen zijn met objecten.
Leer meer over de basis en de software-engineeringconcepten achter OOP door te starten met onze cursus objectgeoriënteerd programmeren met Python.
Encapsulatie is een fundamenteel concept in OOP. Het betekent dat je de data en de methoden van een object groepeert en de details verbergt voor de buitenwereld. Zie encapsulatie als een proces dat een ‘capsule’ (een object) creëert met zijn eigen data en manieren om die te manipuleren.
Het belangrijkste doel van encapsulatie is om:
Privémethoden zijn cruciaal om deze encapsulatie te bereiken door de interne implementatiedetails van een klasse te verbergen.
Door een methode privé te maken, laat je andere programmeurs weten dat deze methode niet bedoeld is om direct te worden aangeroepen. Dit kan bugs en fouten voorkomen door ervoor te zorgen dat de interne status van een object alleen op gecontroleerde manieren kan worden gewijzigd.
Hier introduceren we privémethoden, de syntaxis om ze te definiëren, hoe je ze implementeert met praktijkvoorbeelden en de best practices voor het gebruik ervan.
Wat zijn privémethoden?
Privémethoden in objectgeoriënteerd programmeren (OOP) zijn functies binnen een klasse die uitsluitend voor intern gebruik zijn bedoeld. Ze kapselen de functionaliteit van een klasse in, zodat de interne werking afgeschermd blijft van externe interactie.
Deze encapsulatie zorgt voor een laag van abstractie, waardoor de klasse de controle behoudt over zijn interne toestand en gedrag, en zijn implementatie kan wijzigen zonder externe code die erop vertrouwt te beïnvloeden.
In Python geef je volgens de conventie privémethoden aan door de methodenaam te laten voorafgaan door een enkele underscore (_) of dubbele underscores (__). Dit is een hint voor ontwikkelaars over de beoogde scope van de methode en is slechts een conventie.
Hoewel deze conventie geen strikte privacy afdwingt zoals in sommige andere talen, is het binnen de Python-community een gerespecteerde manier om het beoogde gebruik van de methode te signaleren. Later gaan we dieper op deze aspecten in.
De syntaxis van privémethoden
Er zijn twee verschillende manieren om privémethoden te definiëren; we bekijken ze aan de hand van voorbeelden.
We kunnen een privémethode definiëren met een enkele underscore vóór de functienaam:
Deze definitie is slechts een conventie voor programmeurs, want de functie is nog steeds van buiten de klasse toegankelijk, al wordt dat niet aanbevolen.
Als dit de eerste keer is dat je over klassen in Python hoort, raden we je aan om eerst onze beginnersvriendelijke tutorial over Classes te bekijken.
Laten we een object maken en proberen de gemaakte privémethode te benaderen:
Er is nog een syntaxis voor het definiëren van privémethoden in Python met dubbele underscores. Die ziet er zo uit:
Als we proberen de privémethode van buiten de klasse te benaderen, wordt er een AttributeError opgegooid, wat aangeeft dat deze niet rechtstreeks via de functienaam kan worden aangeroepen.
Samengevat de syntaxis van privémethoden in Python:
Privémethoden in Python implementeren
Als praktijkvoorbeeld nemen we een veilige en gebruiksvriendelijke BankAccount-klasse om financiële transacties voor een gebruiker te beheren. De vereisten voor bankrekeningen zijn:
Natuurlijk heeft een bankrekening meer functionaliteiten, zoals saldocontrole, valutaconversie en renteafhandeling — maar om het eenvoudig te houden, negeren we die in onze implementatie.
Laten we deze oplossing implementeren en de code begrijpen.
We maken eerst een
BankAccountclassdie al het gewenste gedrag en de functionaliteit omvat die nodig zijn voor een BankAccount-object.De
BankAccount-klasse heeft een privé-attribuut__balanceen een privémethode__update_balance:__balance): Dit is een attribuut van deBankAccount-klasse dat het huidige rekeningsaldo opslaat. Het is als privé gemarkeerd door de naam te laten voorafgaan door twee underscores (__). Dit betekent dat het alleen bedoeld is om binnen de klasse zelf te worden benaderd. Het wordt bijvoorbeeld aangepast door de methodendeposit,withdrawen__update_balance. Externe toegang tot dit attribuut wordt niet aanbevolen.__update_balance): Het doel van deze methode is het bijwerken van het rekeningsaldo. Ze wordt aangeroepen door de methodetransferom tijdens een overboeking het saldo van de ontvangende rekening bij te werken. Door hier een privémethode te gebruiken, kapsel je de logica voor het bijwerken van het saldo in, zodat dit alleen kan op gecontroleerde manieren die door de klasse zijn gedefinieerd.Voel je vrij om een nieuw Python-bestand te maken, de bovenstaande en onderstaande code te kopiëren en te plakken, en uit te voeren om het zelf te zien.
Je ziet dan de onderstaande output:
Gefeliciteerd! Je hebt je BankAccount-oplossing gemaakt met een privémethode!
Op basis van de output zien we dat bij de gebruikelijke bankhandelingen zoals storten, opnemen en overboeken, het gebruikelijke logische gedrag van een bankrekening wordt gevolgd.
De __init__-methode: is dit een privémethode?
Je hebt waarschijnlijk de methode
__init__gezien in het BankAccount-voorbeeld. Omdat deze ook dubbele underscores gebruikt, vraag je je misschien af of dit ook een privémethode is.De methode
__init__wordt niet beschouwd als een privémethode op dezelfde manier als methoden die voor privacy met dubbele underscores worden voorafgegaan.In plaats daarvan is het een onderdeel van speciale methoden in Python, vaak “dunder”-methoden genoemd (afkorting van “double underscore”), die een specifieke rol in de taal hebben. Andere voorbeelden van zulke speciale methoden zijn
__str__,__repr__en__del__.Laten we begrijpen hoe deze speciale methode in ons voorbeeld is gebruikt:
Zoals we zien, is de methode
__init__de constructor voor een klasse. Deze wordt automatisch aangeroepen wanneer een nieuw exemplaar van de klasse wordt gemaakt, en wordt gebruikt om de attributen van het object te initialiseren. Voor de klasseBankAccountwordt de methode__init__gebruikt om de beginwaarden in te stellen voor de attributenaccount_holderen__balance.Geavanceerde concepten: name mangling in Python
Eerder gaven we aan dat privémethoden in Python slechts een conventie zijn en dat de Python-taal, in tegenstelling tot andere programmeertalen, privacy niet strikt afdwingt.
Dat klopt: we zagen dat privémethoden direct konden worden benaderd bij gebruik van een enkele underscore, maar dat de toegang werd beperkt bij gebruik van een dubbele underscore.
Waarom? Vanwege een concept dat “name mangling” wordt genoemd in Python.
Wanneer je een attribuutnaam laat voorafgaan door dubbele underscores, wijzigt Python de naam automatisch door een enkele underscore en de klassenaam vóór de oorspronkelijke attribuutnaam toe te voegen.
Deze gewijzigde naam is hoe het attribuut intern binnen de klasse wordt opgeslagen. Het proces van het op deze manier wijzigen van de naam staat bekend als name mangling.
Name mangling is om twee redenen nuttig:
Laten we een voorbeeld bekijken om dit beter te begrijpen.
In dit voorbeeld zijn
__private_attributeen__private_methodonderhevig aan name mangling. Intern worden ze respectievelijk opgeslagen als_MyClass__private_attributeen_MyClass__private_method. Pogingen om ze met hun oorspronkelijke namen van buiten de klasse te benaderen, resulteren in eenAttributeError.Je kunt ze echter nog steeds benaderen met hun gemanglede namen:
Hoewel name mangling attributen minder toegankelijk maakt, is het belangrijk om te benadrukken dat dit geen waterdichte manier is om privacy in Python te garanderen. Het is vooral een conventie om aan te geven dat een attribuut is bedoeld voor intern gebruik binnen de klasse.
Best practices voor het gebruik van privémethoden en -variabelen
Privémethoden en -variabelen effectief inzetten vraagt om het volgen van bepaalde best practices. Deze zorgen ervoor dat je code niet alleen functioneel is, maar ook duidelijk, onderhoudbaar en veilig.
Hier zijn enkele best practices om te volgen:
_). Dit is een conventie in Python die andere ontwikkelaars signaleert dat het attribuut of de methode “beschermd” is en niet direct moet worden benaderd.__). Dit triggert name mangling en maakt het lastiger (maar niet onmogelijk) om het attribuut of de methode van buiten de klasse te benaderen.Tot slot is het belangrijk om consistent te zijn met je codeerconventies. Houd je aan de naamgevingsconventies en gebruik ze consequent in je codebase. Dit maakt je code begrijpelijker en onderhoudbaarder voor andere ontwikkelaars én voor je toekomstige zelf.
Conclusie
In deze tutorial heb je kennisgemaakt met de concepten achter privémethoden, hun syntaxis en wanneer je ze kunt gebruiken. We hebben ook meerdere voorbeelden gezien die illustreren hoe je ze in je volgende codeerproject kunt toepassen. Tot slot hebben we enkele best practices bekeken om in gedachten te houden bij het gebruik ervan.
Voor verdere verdieping kun je de Python Programming Skill Track en de cursus Object-oriented Programming in Python bekijken.