Geekflare is supported by our audience. We may earn affiliate commissions from buying links on this site.
In Development Last updated: April 12, 2023
Share on:
Invicti Web Application Security Scanner – the only solution that delivers automatic verification of vulnerabilities with Proof-Based Scanning™.

One of Python’s lesser-known yet valuable features is the ability to implement magic methods on objects. Using magic methods, we can write cleaner code that is intuitive and easy to understand.

With magic methods, we can create interfaces for interacting with objects in a way that feels more Pythonic. This article will introduce you to magic methods, discuss best practices for creating them and explore the common magic methods you will encounter.

What Are Magic Methods?

Magic methods are Python methods that define how Python objects behave when common operations are carried out on them. These methods are distinctly defined with double underscores before and after the method name.

As a result, they are commonly called dunder methods, as in double underscore. A common dunder method you might have already encountered is the __init__() method that is used for defining class constructors.

Typically, dunder methods are not meant to be called directly in your code; rather, they will be called by the interpreter as the program is running.

Why Are Magic Methods Useful?

Magic methods are a useful concept in Object Oriented Programming in Python. Using them, you specify the behavior of your custom data types when they are used with common, built-in operations. These operations include:

🟢 Arithmetic operations

🟢 Comparison operations

🟢 Life cycle operations

🟢 Representation operations

The following section will discuss how to implement magic methods that define how the application behaves when used in all of the above categories.

How to Define Magic Methods

As mentioned earlier, magic methods specify the behavior of objects. As such, they are defined as part of the object’s class. Because they are part of the object class, they take in as the first argument self which is a reference to the object itself.

They can take in additional arguments depending on how they will be called by the interpreter. They are also distinctly defined with two underscores before and after their names.


Much of what we have discussed so far seems theoretical and abstract. In this section, we will implement a simple Rectangle class.

This class will have length and width properties. Using the __init__ method, you can specify these properties on instantiation. In addition, you will be able to compare different rectangles to see if it equal, less, or greater than another one using the ==, < and > operators. Lastly, the rectangle should be capable of providing a meaningful string representation.

Setting up the Coding Environment

To follow along with this walkthrough, you will need a Python runtime environment. You can use a local one, or you can use the online Geekflare Python compiler.

Creating the Rectangle Class

First, let’s start by defining the Rectangle class.

class Rectangle:

Creating the Constructor Method

Next, let’s create our first magic method, the class constructor method. This method will take in the height and width and store them as attributes on the class instance.

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

Creating a Magic Method for String Representation

Next, we want to create a method that allows our class to generate a human-readable string to represent the object. This method will be called whenever we call the str() function passing in an instance of the Rectangle class as an argument. This method will also be called when you call functions that expect a string argument, such as the print function.

class Rectangle:
    def __init__(self, height, width):
        self.height = height
        self.width = width

    def __str__(self):
        return f'Rectangle({self.height}, {self.width})'

The __str__() method should return a string that you would want to represent the object. In this case, we are returning a string of the format Rectangle(<height>, <width>) where height and width are the stored dimensions of the rectangle.

Creating Magic Methods for Comparison Operations

Next, we want to create comparison operators for the equal to, less than, and greater than operations. This is called operator overloading. To create these, we use the magic methods __eq__, __lt__ and __gt__ respectively. These methods will return a boolean value after comparing the areas of the rectangles.

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

As you can see, these methods take in two parameters. The first is the current rectangle, and the second is the other value it is being compared against. This value can be another Rectangle instance or any other value. The logic for how the comparison and the conditions under which the comparison will return true are completely up to you.

Common Magic Methods

In this next section, we will discuss the common magic methods you will encounter and use.

#1. Arithmetic Operations


Arithmetic magic methods are called when an instance of your class is placed at the left-hand side of an arithmetic sign. The method will be called with two arguments, the first being a reference to the instance. The second value is the object to the right of the sign. The methods and signs are as follows:

Addition__add__+Implements addition.
Subtraction__sub__Implements subtraction.
Multiplication__mul__*Implements multiplication
Division__div__/Implements division.
Floor division__floordiv__//Implements floor division.

#2. Comparison Operations


Like the arithmetic magic methods, these methods are called when an instance of the class they are defined for is placed to the left of the comparison operator. Also, like arithmetic magic methods, they are called with two parameters; the first is a reference to the instance of the object. The second is a reference to the value on the right side of the sign.

Less than__lt__<Implements the less than comparison
Greater than__gt__>Implements the greater than comparison
Equal to__eq__==Implements the equal to comparison
Less than or equal to__le__>=Implements the less than or equal to comparison
Greater than or equal to__ge__<=Implements the greater than or equal to comparison

#3. Lifecycle Operations


These methods will be called in response to the different lifecycle methods of an object, such as being instantiated or deleted. The constructor, __init__ falls under this category. The common methods in this category are listed in the table below:

Constructor__init__This method is called whenever an object of the class it is defined for is deleted. It can be used to perform clean-up actions such as closing any files it had opened.
Deletion__del__This method is called whenever an object of the class it is defined for is deleted. It can be used to perform clean-up actions such as closing any files it had opened.
New__new__The __new__ method is called first when an object of the specified class is instantiated. This method is called before the constructor and takes in the class as well as any additional arguments. It returns an instance of the class. For the most part, it is not too useful, but it is covered in detail here.

#4. Representation Operations

Str__str__Returns a human-readable string representation of the object. This method is called when you call the str() function, passing an instance of the class as an argument. It is also called when you pass in the instance to the print() and format() functions. It is meant to provide a string that is understandable by the end-user of the application.
Repr__repr__Returns a string representation of the object that is used by the developer. Ideally, the string returned should be information-rich such that you can construct an identical instance of the object from just the string.

Best Practices for Creating Magic Methods

Magic methods are incredible and will simplify your code. However, it is important to keep the following things in mind when you use them.

  • Use them sparingly – Implementing too many magic methods in your classes makes your code hard to understand. Limit yourself to implementing only the essential ones.
  • Ensure you understand the performance implications of methods such as __setatrr__ and __getattr__ before using them.
  • Document the behavior of your magic methods so other developers may know exactly what they do. This makes it easier for them to use them and debug when necessary.

Final Words

In this article, I introduced magic methods as a way to make classes that can be used with built-in operations. I also discussed how they are defined and went through an example of a class that magic methods implemented. Next, I mentioned the different methods that you are likely going to use and need before sharing a few best practices to keep in mind.

Next, you might want to learn how to implement the Counter class in Python.

  • Anesu Kafesu
    Full stack web developer and technical writer. Currently learning AI.
Thanks to our Sponsors
More great readings on Development
Power Your Business
Some of the tools and services to help your business grow.
  • Invicti uses the Proof-Based Scanning™ to automatically verify the identified vulnerabilities and generate actionable results within just hours.
    Try Invicti
  • Web scraping, residential proxy, proxy manager, web unlocker, search engine crawler, and all you need to collect web data.
    Try Brightdata
  • is an all-in-one work OS to help you manage projects, tasks, work, sales, CRM, operations, workflows, and more.
    Try Monday
  • Intruder is an online vulnerability scanner that finds cyber security weaknesses in your infrastructure, to avoid costly data breaches.
    Try Intruder