Intro to “Dunder” Methods in Python
When learning Python, one thing I learned that was different in other languages are the double underscore (“dunder”, magic, or special) methods that can be used in classes. There are definitely ways to do this in other languages, but python makes the process a lot easier.
A class can implement certain operations that are invoked by special syntax (such as arithmetic operations or subscripting and slicing) by defining methods with special names. This is Python’s approach to operator overloading, allowing classes to define their own behavior with respect to language operators.
— Python’s documentation on what are ‘dunder’ methods
Below I have an example Pet class with the most-used dunder methods.
class Pet: def __init__(self, name, species):
self.name = name
self.species = species def __repr__(self):
return "Pet('{}', '{}')".format(self.name, self.species) def __str__(self):
return "My pet, {}, the {}".format(self.name, self.species) def __add__(self, other):
if isinstance(other, Pet):
return "{} and {}".format(self.name, other.name)
return NotImplemented def __del__(self):
return "{}, the {} is deleted".format(self.name, self.species)# Creating an instance
my_pet = Pet("Cookie Dough", "dog")
johns_pet = Pet("Henry", "cat")
__init__
This was is very similar to constructor in other languages. It is what happens when the class is initialized. So in the example, we are adding a name and a species.
__repr__
This is usually used for debugging purposes, Python classifies this as “[a] built-in function to compute the “official” string representation of an object. […] This is typically used for debugging, so it is important that the representation is information-rich and unambiguous.”
So, when you call print(repr(my_pet))
it will return Pet(‘Cookie Dough', ‘dog')
.
__str__
The python docs consider this, “to compute the “informal” or nicely printable string representation of an object.” So while repr is for developer purposes, this is what is normally seen by the user of the application.
When you call print(str(my_pet))
it will return My pet, Cookie Dough, the dog
.
__add__
This is what happens if someone tries to add two of the same classes together. The highest-level example I can provide is print(1 + 2)
. Maybe there is a reason why you would want something like this in your classes (hint: spoiler for later).
When you call print(my_pet + johns_pet)
it will return Cookie Dough and Henry
.
__del__
This mehtod is called when the instance is about to be destroyed. In the case above, when del my_pet
is ran, then the system will print Cookie Dough, the dog is deleted
.
A real life application
Taking a look inside the source code for the datetime module, there is a __add__ method for the timedelta class.
A picture of the code is listed below, but what it is doing firstly is checking if both sides are a timedelta format (if it is not then it will raise a NotImplemented error) and then added the two dates together.
Additional resources:
- Special Method Names : python documentation
- Python OOP Tutorial 5: Special (Magic/Dunder) Methods by Corey Schafer
Final notes…
Is there anything I missed? Any additional resources you want added to this page? Comment down below to help out!