Magic Methods in Python - Dunder Methods
Published:
Magic methods are the methods that has two underscores as the prefix and suffix to the method name. These are also called dunder methods which is an adopted name for double underscores(methods with double underscores). init, str are some magic methods. These are a set of special methods that could be used to enhance your classes in python.
The dunder methods are also usually used for scenarios like operator overloading and allow you to emulate the behavior of the built-in types. We will start by creating a class, implementing a dunder method or two, see available dunder/magic methods that can be used to enrich the functionality of a custom class.
Creating a custom String class:
>>> class String:
... def __init__(self, string):
... self.string = string
...
>>> string = String("thetaranights.com")
>>> print(string)
<__main__.String object at 0x7fec2fad2400>
>>>
Even before we realize, we have made use of one of those many magic methods. The init method is a magic method. init is a method where you’d initialize instance attributes and other init activities. People like to call it a constructor. Think about it for a while, the method already takes the instance (self) as a parameter. Before even init is called a blank object is created. The init method then dynamically initializes each member. Taking self as a parameter means the object is already created before init is called.
Earlier in the blog, we said that magic methods allows us to emulate the behavior of the built-in types. The result from the print(string) doesn’t really give us what we would generally want. We can implement a magic method repr to present to the user of the String class a better string representation.
>>> class String:
... def __init__(self, string):
... self.string = string
... def __repr__(self):
... return "String Object: {string}".format(string=self.string)
...
>>>
>>> string = String("thetaranights.com")
>>> print(string)
String Object: thetaranights.com
>>>
In the above code snippet, we have implemented the repr magic method to return a better string representation of our String class’s instance.
Another example of dunder method:
Say we want to get the results from concatenating our custom String object with a string, we would do.
>>> print(string + " Thanks for visiting")
TypeError: unsupported operand type(s) for +: 'String' and 'str'
In order for this to work we need to implement the add magic method to our class String.
>>> class String:
... def __init__(self, string):
... self.string = string
... def __repr__(self):
... return "Object String: {string}".format(string=self.string)
... def __add__(self, to_concatenate):
... return self.string + to_concatenate
...
>>>
>>> string = String("thetaranights.com")
>>>
>>> print(string + " thanks for visiting")
thetaranights.com thanks for visiting
>>>
Now that we have implemented the add magic method, we can now use the + operator. Following is the list of magic methods available:
Available Magic Methods
Binary Operators
| Operator | Method | |———-|——–| | + | object.add(self, other) | | - | object.sub(self, other) | | * | object.mul(self, other) | | // | object.floordiv(self, other) | | / | object.truediv(self, other) | | % | object.mod(self, other) | | ** | object.pow(self, other[, modulo]) | | « | object.lshift(self, other) | | » | object.rshift(self, other) | | & | object.and(self, other) | | ^ | object.xor(self, other) | | | | object.or(self, other) |
Extended Assignment
| Operator | Method | |———-|——–| | += | object.iadd(self, other) | | -= | object.isub(self, other) | | *= | object.imul(self, other) | | /= | object.idiv(self, other) | | //= | object.ifloordiv(self, other) | | %= | object.imod(self, other) | | **= | object.ipow(self, other[, modulo]) | | «= | object.ilshift(self, other) | | »= | object.irshift(self, other) | | &= | object.iand(self, other) | | ^= | object.ixor(self, other) | | |= | object.ior(self, other) |
Unary Operators
| Operator | Method | |———-|——–| | - | object.neg(self) | | + | object.pos(self) | | abs() | object.abs(self) | | ~ | object.invert(self) | | complex() | object.complex(self) | | int() | object.int(self) | | long() | object.long(self) | | float() | object.float(self) | | oct() | object.oct(self) | | hex() | object.hex(self) |
Comparison Operators
| Operator | Method | |———-|——–| | < | object.lt(self, other) | | <= | object.le(self, other) | | == | object.eq(self, other) | | != | object.ne(self, other) | | >= | object.ge(self, other) | | > | object.gt(self, other) |
That’s my little introduction to dunder/magic methods in Python. You should also read this article on Debugging with breakpoint in python3.7 https://www.thetaranights.com/debugging-with-breakpoint-in-python3-7/
