The Python Magic Method is a unique method that adds underscores at the beginning and end of the method name. The Python magic method is also referred to as the "dunder method". Examples of dunder methods include __init__(), __str__() and others. Magic methods are not designed to be invoked directly by you; instead, they are intended to be invoked by the class that has the magic method internally. For example, str() calls the __str__ () magic method and renders the object in a string format. Likewise, the operator "+" is used to internally invoke the dunder method "__add__." An object can have numerous magic methods.
The built-in classes define many magic methods. The dir() function can be used to get the magic method inherited by a class. The code below generates a list of magic methods in the String class.
print(list(filter(lambda x: x.startswith('__') and x.endswith('__'),
dir(str))))
['__add__', '__class__', '__contains__', '__delattr__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__','__getnewargs__', '__gt__', '__hash__', '__init__',
'__init_subclass__','__iter__', '__le__', '__len__', '__lt__',
'__mod__', '__mul__', '__ne__','__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__rmod__', '__rmul__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__']
Let's see how our actions or methods invoke the magic method internally.
>>> str(True)
'True'
>>>True.__str__()
'True'
From the code above, we use the str() function to get the string format of the boolean value "True". The str() function invokes the magic method "__str__" internally and converts the boolean to a string. We also used the magic method "__str__" directly to get the same result. However, as enunciated initially, magic methods are not supposed to be called directly but internally through some certain method and action. This demonstrates how the magic method is invoked internally by our actions.
Generally, the magic method gives us more control over how our application behaves. Let's see how we can create our own custom classes and override some of these magic methods to alter the behavior of our application.
__Add__() Method:
This method is called when we attempt to add two numbers with the operator "+". Let's illustrate how we can customize the magic method "__add__". We will override the Magic method to create our own custom logic.
class Shape():
def __init__(self, area):
self.area = area
def __add__(self, others):
return self.area + others.area
circle = Shape(15)
square = Shape(20)
totalArea = circle + square
print(totalArea)
#Output: 35
According to the example above, I have a class named "Shape" and in this class, the user can pass the area of the shape into the init constructor. The attribute of the class "area" holds an integer value. The instances of the class circle and square contain the integer values 15 and 20 in their attribute respectively. The __add__(self, other) method is called when we perform the operation circle + square, and it returns 35.
__Str__() Method:
The __str__() method is executed when we want to print an object in a human-readable format. Let's illustrate how we can override the __str__() functionality.
class Animal():
def __init__(self, name, species):
self.name = name
self.species = species
def __str__(self):
return f"The name of the animal is {self.name} and its a {self.species}"
instance1 = Animal("fish", "pisces")
instance2 = Animal("Dog", "Mammal")
print(instance1)
print(instance2)
#Output: The name of the animal is a fish and its a pisces
#Output: The name of the animal is a Dog and its a Mammal
As usual, the __str__() function should attempt to return a user-friendly representation of the object.
__len__():
This method returns the length of an object. It is internally invoked when we use the function len().
Class Animal():
def __init__(self, name):
self.name = name
def __len__(self):
x = self.name.count("p")
return x
instance1 = Animal("hipopotemus")
print(len(instance1))
#output: 2
In the example above, we override the __len__() functionality to only count "p" characters. When we used the len() function on the instance, it internally calls the __len__(self) method and returns a value of 2.
__init__() Method:
The __init__() method is called after the instance of a class is created. Instantiating a new instance of a class executes this constructor. In the previous example, when we try to execute this:
instance1=Animal("hipopotemus")
Then __init__() method is executed.
We can also override the __init__() functionality to enrich our program.
__ge__() Method:
This is the greater than or equal to method. This method is invoked internally when we attempt to use the >= symbol. This method returns True or False depending on the outcome. Sometimes we will want to override the __ge__() functionality and provide our own custom logic.
class Shape():
def __init__(self, area):
self.area = area
def __ge__(self, others):
return self.area >= others.area
circle = Shape(15)
square = Shape(20)
print(circle >= square)
#Output: False
Summary
Generally, the magic method was intended to be private and not to be invoked directly. The method was meant to be invoked internally by the class that has the magic method. The magic methods give us the power to control the behavior of our application.
The magic method can be used to enrich the functionality of our class and create custom logic best suited for us.