Magic/Dunder Methods in Python

Dunder stands for double underscore and rhymes with thunder. Unlike thunder, dunder method doesn’t have to make noise, it works like magic✨ — behind your optical sensory. In this article we’ll refer to magic/dunder method as dunder method.
Side note: I learned what dunder stood for in my first CS class and I guess it has stuck with me since then. Later, I might also have been a little nuisance by blurting what it stood for. 🤐 :flips_mane:
Dunder method starts and end with double underscore _
, like __init__
, __main__
, __str__
.
Let’s model a vaccine information present out there in wild:
On running the file, we get:
<__main__.Vaccine object at 0x7fc8480dce50>
We receive something that looks like where v1
instance of the class Vaccine is located. What’s happening behind the print
statement?
print
is basically printing string format of the Vaccine object using __str__
method like we have toString()
in Java. We can explicitly call __str__()
on v1
instance see the same result:
On running the file, we see:
implicit print of v1 instance: <__main__.Vaccine object at 0x7f9e701e4e50>
explicit print of v1 instance: <__main__.Vaccine object at 0x7f9e701e4e50>
Now let’s override the __str__
method to give us more high-level details about the v1
instance:
On running the file, we can get:
Generic Name: Moderna, Expiry date: 2021-07-07, Against: coronavirus 🦠
So you see, you can actually override builtin dunder methods that meets your need. You need to work, no magic. 😁
Now let’s checkout some builtin dunder methods in python environment:

Can you see how many different ways we can use __add__
method()? Besides integers, we can use it for concatenating list and strings. Like __str__
method, there is an implementation behind it which overloads the __add__
method.
Let’s override builtin __add__
method in our class Vaccine
.
On running the file, we get:
======== __add__ and ___repr__ ==========
v1 + v2 = [Moderna, PFizer]
======== __call__ ==========
Instance v1 call: 👺 hehawhehaw I'll soar your heat for max 2 days to make you resistant most of the time, says Moderna 🎃
Instance v2 call: 👺 hehawhehaw I'll soar your heat for max 2 days to make you resistant most of the time, says PFizer 🎃
The output is a finish touch. New dunder methods involved here are __add__
, __repr__
, and __call__
.
As we have told earlier, we are going to override __add__
method for adding two Vaccine instance. We did that by adding our own implementation to the __add__
method. If we did not have __repr__
method, then the result of v1 + v2
would have been
[<__main__.Vaccine object at 0x7ff0a81edfd0>, <__main__.Vaccine object at 0x7ff0a81edf10>]
So __repr__
came to our help by providing us an implementation to present the instances more human friendly.
Also included a s small treat with __call__
method. I’ve very recently come across an instance of class being called using call()
, so had a quick lookup. __call__
method is used to call an instance of an object like how __init__
is used to call Class.
In conclusion, dunder/magic methods are invoked implicitly behind some operator such as str()
, +
, —
etc. Hope that was helpful!
My next article would be something on memory 🧠. Thank you for reading. See you then!