Een van de minder bekende maar waardevolle functies van Python is de mogelijkheid om magische methoden op objecten te implementeren. Met behulp van magische methoden kunnen we schonere code schrijven die intuïtief en gemakkelijk te begrijpen is.
Met magische methoden kunnen we interfaces creëren voor interactie met objecten op een manier die meer Pythonisch aanvoelt. Dit artikel laat je kennismaken met magische methoden, bespreekt best practices voor het maken ervan en onderzoekt de gebruikelijke magische methoden die je tegenkomt.
Wat zijn magische methoden?
Magic-methoden zijn Python-methoden die bepalen hoe Python-objecten zich gedragen wanneer er algemene bewerkingen op worden uitgevoerd. Deze methoden zijn duidelijk gedefinieerd met dubbele onderstrepingstekens voor en na de naam van de methode.
Als gevolg hiervan worden ze gewoonlijk dunder-methoden genoemd, zoals in dubbel onderstrepingsteken. Een veelgebruikte dunder-methode die u misschien al bent tegengekomen, is de __init__()-methode die wordt gebruikt voor het definiëren van klassenconstructors.
Doorgaans zijn dunder-methoden niet bedoeld om rechtstreeks in uw code te worden aangeroepen; in plaats daarvan worden ze door de tolk aangeroepen terwijl het programma wordt uitgevoerd.
Waarom zijn magische methoden nuttig?
Magische methoden zijn een nuttig concept in objectgeoriënteerd programmeren in Python. Door ze te gebruiken, specificeert u het gedrag van uw aangepaste gegevenstypen wanneer ze worden gebruikt met algemene, ingebouwde bewerkingen. Deze bewerkingen omvatten:
🟢 Rekenkundige bewerkingen
🟢 Vergelijkingsbewerkingen
🟢 Levenscyclusoperaties
🟢 Vertegenwoordigingsoperaties
In het volgende gedeelte wordt besproken hoe magische methoden kunnen worden geïmplementeerd die bepalen hoe de toepassing zich gedraagt wanneer deze in alle bovenstaande categorieën wordt gebruikt.
Hoe magische methoden te definiëren
Zoals eerder vermeld, specificeren magische methoden het gedrag van objecten. Als zodanig worden ze gedefinieerd als onderdeel van de klasse van het object. Omdat ze deel uitmaken van de objectklasse, nemen ze als eerste argument zelf op, wat een verwijzing is naar het object zelf.
Ze kunnen aanvullende argumenten opnemen, afhankelijk van hoe ze door de tolk worden aangeroepen. Ze zijn ook duidelijk gedefinieerd met twee onderstrepingstekens voor en achter hun naam.
Implementatie
Veel van wat we tot dusver hebben besproken, lijkt theoretisch en abstract. In deze sectie zullen we een eenvoudige Rectangle-klasse implementeren.
Deze klasse heeft lengte- en breedte-eigenschappen. Met behulp van de __init__-methode kunt u deze eigenschappen specificeren bij instantiëring. Bovendien kunt u verschillende rechthoeken vergelijken om te zien of deze gelijk, kleiner of groter zijn dan een andere met behulp van de operatoren ==, < en >. Ten slotte moet de rechthoek een betekenisvolle tekenreeksrepresentatie kunnen bieden.
Opzetten van de codeeromgeving
Om deze walkthrough te volgen, hebt u een Python-runtime-omgeving nodig. U kunt een lokale gebruiken, of u kunt de online epcdream.nl Python-compiler gebruiken.
De rechthoekklasse maken
Laten we eerst beginnen met het definiëren van de klasse Rectangle.
class Rectangle: pass
De constructormethode maken
Laten we vervolgens onze eerste magische methode maken, de class constructor-methode. Deze methode neemt de hoogte en breedte op en slaat ze op als attributen op de klasse-instantie.
class Rectangle: def __init__(self, height, width): self.height = height self.width = width
Een magische methode maken voor tekenreeksrepresentatie
Vervolgens willen we een methode maken waarmee onze klasse een door mensen leesbare string kan genereren om het object weer te geven. Deze methode wordt aangeroepen wanneer we de functie str() aanroepen die een instantie van de klasse Rectangle als argument doorgeeft. Deze methode wordt ook aangeroepen wanneer u functies aanroept die een stringargument verwachten, zoals de printfunctie.
class Rectangle: def __init__(self, height, width): self.height = height self.width = width def __str__(self): return f'Rectangle({self.height}, {self.width})'
De __str__() methode zou een string moeten teruggeven die je het object zou willen voorstellen. In dit geval retourneren we een tekenreeks met de notatie Rechthoek(
Magische methoden maken voor vergelijkingsbewerkingen
Vervolgens willen we vergelijkingsoperatoren maken voor bewerkingen gelijk aan, kleiner dan en groter dan. Dit wordt overbelasting van de operator genoemd. Om deze te maken, gebruiken we respectievelijk de magische methoden __eq__, __lt__ en __gt__. Deze methoden retourneren een booleaanse waarde na het vergelijken van de gebieden van de rechthoeken.
class Rectangle: def __init__(self, height, width): self.height = height self.width = width def __str__(self): return f'Rectangle({self.height}, {self.width})' def __eq__(self, other): """ Checking for equality """ return self.height * self.width == other.height * other.width def __lt__(self, other): """ Checking if the rectangle is less than the other one """ return self.height * self.width < other.height * other.width def __gt__(self, other): """ Checking if the rectage is greater than the other one """ return self.height * self.width > other.height * other.width
Zoals u kunt zien, nemen deze methoden twee parameters in beslag. De eerste is de huidige rechthoek en de tweede is de andere waarde waarmee deze wordt vergeleken. Deze waarde kan een andere instantie van Rectangle zijn of een andere waarde. De logica voor hoe de vergelijking en de voorwaarden waaronder de vergelijking waar zal zijn, is geheel aan jou.
Gemeenschappelijke magische methoden
In dit volgende gedeelte zullen we de gebruikelijke magische methoden bespreken die je zult tegenkomen en gebruiken.
#1. Rekenkundige bewerkingen
Rekenkundige magische methoden worden aangeroepen wanneer een instantie van uw klasse aan de linkerkant van een rekenkundig teken wordt geplaatst. De methode wordt aangeroepen met twee argumenten, de eerste is een verwijzing naar de instantie. De tweede waarde is het object rechts van het teken. De methoden en tekens zijn als volgt:
NameMethodSignDescriptionAddition__add__+Implementeert optellen. Subtraction__sub__–Implementeert aftrekken.Multiplication__mul_*Implementeert vermenigvuldigingDivision__div__/Implementeert division.Floor division__floordiv__//Implementeert floor division.
#2. Vergelijkende bewerkingen
Net als de rekenkundige magische methoden, worden deze methoden aangeroepen wanneer een instantie van de klasse waarvoor ze zijn gedefinieerd, links van de vergelijkingsoperator wordt geplaatst. Ook worden ze, net als rekenkundige magische methoden, aangeroepen met twee parameters; de eerste is een verwijzing naar de instantie van het object. De tweede is een verwijzing naar de waarde aan de rechterkant van het teken.
NameMethodSignDescriptionLess than__lt__
#3. Levenscyclus operaties
Deze methoden worden aangeroepen als reactie op de verschillende levenscyclusmethoden van een object, zoals instantiëren of verwijderen. De constructor, __init__ valt onder deze categorie. De gebruikelijke methoden in deze categorie staan in de onderstaande tabel:
NameMethodDescriptionConstructor__init__Deze methode wordt aangeroepen wanneer een object van de klasse waarvoor het is gedefinieerd, wordt verwijderd. Het kan worden gebruikt om opruimacties uit te voeren, zoals het sluiten van geopende bestanden.Deletion__del__Deze methode wordt aangeroepen wanneer een object van de klasse waarvoor het is gedefinieerd, wordt verwijderd. Het kan worden gebruikt om opruimacties uit te voeren, zoals het sluiten van geopende bestanden. New__new__De methode __new__ wordt als eerste aangeroepen wanneer een object van de opgegeven klasse wordt geïnstantieerd. Deze methode wordt vóór de constructor aangeroepen en neemt zowel de klasse als eventuele aanvullende argumenten op. Het retourneert een instantie van de klasse. Voor het grootste deel is het niet zo handig, maar het wordt hier in detail behandeld.
#4. Vertegenwoordigingsoperaties
NameMethodDescriptionStr__str__Retourneert een door mensen leesbare tekenreeksrepresentatie van het object. Deze methode wordt aangeroepen wanneer u de functie str() aanroept en een instantie van de klasse als argument doorgeeft. Het wordt ook aangeroepen wanneer u de instantie doorgeeft aan de functies print() en format(). Het is bedoeld om een tekenreeks te bieden die begrijpelijk is voor de eindgebruiker van de toepassing.Repr__repr__Retourneert een tekenreeksrepresentatie van het object dat door de ontwikkelaar wordt gebruikt. Idealiter zou de geretourneerde tekenreeks informatierijk moeten zijn, zodat u een identiek exemplaar van het object kunt construeren met alleen de tekenreeks.
Best practices voor het maken van magische methoden
Magische methoden zijn ongelooflijk en zullen uw code vereenvoudigen. Het is echter belangrijk om de volgende dingen in gedachten te houden wanneer u ze gebruikt.
- Gebruik ze spaarzaam – Als u te veel magische methoden in uw klassen implementeert, wordt uw code moeilijk te begrijpen. Beperk jezelf tot het implementeren van alleen de essentiële.
- Zorg ervoor dat u de prestatie-implicaties van methoden zoals __setatrr__ en __getattr__ begrijpt voordat u ze gebruikt.
- Documenteer het gedrag van uw magische methoden, zodat andere ontwikkelaars precies weten wat ze doen. Dit maakt het voor hen gemakkelijker om ze te gebruiken en indien nodig te debuggen.
laatste woorden
In dit artikel heb ik magische methoden geïntroduceerd als een manier om klassen te maken die kunnen worden gebruikt met ingebouwde bewerkingen. Ik heb ook besproken hoe ze zijn gedefinieerd en heb een voorbeeld doorgenomen van een klasse die magische methoden hebben geïmplementeerd. Vervolgens noemde ik de verschillende methoden die u waarschijnlijk gaat gebruiken en nodig hebt, voordat ik een paar best practices deel om in gedachten te houden.
Vervolgens wilt u misschien leren hoe u de Counter-klasse in Python implementeert.