- What are Magic Methods in Python and How to Use Them
- What Are Magic Methods?
- Why Are Magic Methods Useful?
- How to Define Magic Methods
- Implementation
- Setting up the Coding Environment
- Creating the Rectangle Class
- Creating the Constructor Method
- Creating a Magic Method for String Representation
- Creating Magic Methods for Comparison Operations
- Common Magic Methods
- #1. Arithmetic Operations
- #2. Comparison Operations
- #3. Lifecycle Operations
- #4. Representation Operations
- Best Practices for Creating Magic Methods
- Final Words
What are Magic Methods in Python and How to Use Them
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:
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.
Implementation
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.
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(, )'
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(, ) 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(, )' 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:
Name | Method | Sign | Description |
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.
Name | Method | Sign | Description |
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:
Name | Method | Description |
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
Name | Method | Description |
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.