Python magic methods are also known as dunder methods or special methods. But why such dramatic names? They’re used to overwrite or emulate the behavior of built-in functions.
They’re also easy to recognize, as they follow a particular pattern: They have double underscores as prefixes and suffixes. Hence, the name dunder means Double Underscore. They’re referred to as special methods because they add “magic” to your python classes. Common examples are __init__(), __str__(), __call__(), etc. A magic method is generally used to override operations.
Let’s check out some of the popular magic methods
We’ll discuss these methods based on their object usefulness (an object is an instance of a class). The three categories we’ll be focusing on are
- Object Initialization method
- Object Representation Method
- Object Mathematical Operation Method
To understand these methods better, we’ll use a specific business scenario.
The first method we use when creating a class is the initialization method __init__(), which is actually a magic method. This method, also called a constructor, takes care of setting up the object. Let’s create a TeeShirt class
Above is a simple representation of the tee-shirt class, as it includes just the tee-shirt data. With this magic method, we can easily create black and white tee-shirt objects and find out the necessary attributes, as shown below:
From the above example, we see that printing the object variable directly didn’t give us much useful information about the meta-data. It just gives some kind of ID that shows it is a TeeShirt class object, which we already know.
A good way of being able to view all the attributes at once is with an object representation method called __str__(). Let’s add this into our class as a method:
Now, give it a test run:
As we see above, all metadata can now be viewed by just printing the object variable directly. One of the biggest advantages of using Python’s magic methods is that they provide a simple way to make objects behave like built-in types/functions. In this case , t his method is behaving like a str()type function, as a string representation of the object. Another object representation method is __repr__(), which works in a similar way.
Going back to our amateur inventory manager’s goal…
It would be nice to be able to know the sum of all the shirt inventories. Let’s see what happens when we add both shirt objects together.
Python throws a TypeError. This is because the black_shirt and white_shirt variables are still ObjectTypes and cannot perform mathematical operations directly.
Let’s see if we can add the objects using their inventory_count attributes.
That seems to do the trick. However, an even nicer way is to add an object operation method to the TeeShirt class in order to print the object variable without the attributes. Using the magic method __add__()—let’s see how:
Now, give it a test run:
I’ll admit, the above method does not seem like a better choice for this example. It’s good to note that the importance of this method gets even handier as the class gets more complicated and the object instances multiply.
Check out some other useful magic methods and their functionalities below. This could be a bonus tool for upgrading your Python classes.
Some final tips to keep in mind
- Everything in Python is an object.
- You can use the dir() built-in function on an object to see the magic methods inherited by the class. Try out dir(str)or dir(black_shirt)(if you create a black_shirt object).
- Magic methods can be used to emulate the behavior of built-in types of user-defined objects. Therefore, whenever you find yourself trying to manipulate a user-defined object’s output in a Python class, remember: magic methods.