By Md. Sabuj Sarker | 9/27/2017 | General |Beginners

Understanding Magic Methods in Python

Understanding Magic Methods in Python

When someone coming from another programming language first starts to learn Python, they realize that Python is great at keeping things clean. We use indentations instead of curly braces which enforces structuring your code in a better way. You cannot be dirty in Python unless you are very careless or do things randomly.

Python keeps things modular and divides various functionality into different libraries or modules. Even the built in library functions are not globally accessible unless you import them. Many languages are out there that make different functions, classes, etc. globally available. There are a lot of things that are better in design and more clean in appearance in Python.

To keep things beautiful Python has to do a lot of dirty work behind the scenes. One thing is the use of magic methods. Magic methods have nothing to do with wizardry but they do have some programming magic behind them.

Every time you need string representation of any object you call str() on it. In many other languages we have to do a lot of things to make that apparently little thing happen. But how does Python do it? It's all about magic methods. When you want to construct a new array by putting two arrays together you just need to put a plus sign + between them. How does Python do that so easily? Most of the magic of shorter syntax in Python comes from the magic methods in Python.

If we want a string representation of an integer, it is enough to call str() with the integer as the parameter.

>>> i = 6
>>> str(i)
'6'
>>>



Let's see what happens behind the scene. The __str__() is called on the integer object to get the string representation of the integer object.

>>> i = 6
>>> i.__str__()
'6'
>>>



Instead of making our code dirty by the __str__() we use str() and python does the dirty work for us.

Getting Started

To get started you need Python installed on your system. You can use any IDE or code editor you prefer. I am going to use use Python 3.6 and I am going to stick to the IDLE and python console with it for the examples here. Also, I am going to use Jupyter Notebook for working on the longer examples.

Understanding Magic Method With __str__()

With the help of this magic method I will try my best to clear the concept of magic method and prove that str() calls the __str__() method internally.

Let's create an empty class called C and print an instance of it on the console.

class C:
   pass

c1 = C()

print(str(c1))



It outputs:

<__main__.C object at 0x00000226A0021C88>

So, it does not provide some useful information to us. It only provides the object address in memory and the class name. We want something better. We want something that is more useful to humans. Before doing anything useful for mankind, let's try to get the same output in the dirty way.

class C:
   pass

c1 = C()

print(c1.__str__())

 

Outputs:

<__main__.C object at 0x00000226A00A67F0>

So, we have a similar result. Do not get confused by a different hex number. I ran it again and python created the object in a different location of memory.

Now, how do we make it behave in our way? We define the __str__() on the class.

class C:
   def __str__(self):
       return "I am an instance of class C"

c2 = C()

print(str(c2))

Outputs:

I am an instance of class C

Ah! We have a natural representation now. But we want more. We want to give each object a name and tell the str() method to return that name along with some more text.

class C:
   def __init__(self, name="--no name--"):
       self.name = name
   def __str__(self):
       return self.name + " object of class C"

c2 = C("c2")

print(str(c2))

Outputs:

c2 object of class C

So, now it is proven that the work done for str() is done by __str__() behind the scenes. Now, let's move on. Python has a lot of other magic methods for different operators and functions.

Magic Methods for Mathematical Operators

Every operator we use on different types of Python objects carries out its job with the help of some underlying magic method:

  • object.__add__(self, other): this magic method is used for addition + operator on different objects.
  • object.__sub__(self, other): subtraction operator - uses this magic method on different types of object.
  • object.__mul__(self, other): multiplication operator * uses __mul__ method.
  • object.__floordiv__(self, other): floor division operator uses __floordiv__ method behind the scene.
  • object.__truediv__(self, other): division operator / uses the __truediv__ magic method.
  • object.__mod__(self, other): % modulus operator uses __mod__ magic method.
  • object.__pow__(self, other[, modulo]): power operator ** uses __pow__ behind the scene.
  • object.__lshift__(self, other): this magic method is used for left shift operator <<.
  • object.__rshift__(self, other): this magic method is used for right shift operator >>.
  • object.__and__(self, other): this magic method is used for bitwise and &
  • object.__xor__(self, other): this magic method is used for exclusive or operator ^.
  • object.__or__(self, other): this magic method is used for bitwise or operator |.

Enough theory, let's have an example now.

Magic Way of Addition

Create a class called C and create two instances of the class and try to add to them the + operator.

class C:
   pass

c1 = C()
c2 = C()

res = c1 + c2

print(res)

Outputs:

TypeError                                 Traceback (most recent call last)
<ipython-input-14-4fbb186cdb38> in <module>()
     5 c2 = C()
     6 
----> 7 res = c1 + c2
     8 
     9 print(res)

TypeError: unsupported operand type(s) for +: 'C' and 'C'

Hey, that's not an output. That's stack trace of the exception that just occurred.

We cannot use the addition operator on the instances of class C, because class C did not define the  __add__() magic method. So, let's try that now.

class C:
   def __add__(self, other):
       return "this is the result of addition of two instances of class C"

c1 = C()
c2 = C()

res = c1 + c2

print(res)

Outputs:

this is the result of addition of two instances of class C

That may be a fun result but not a very useful one. Let's try another. Let's create a class called Triple and store initial numeric value in it. When we call get_value() on it, it will return three times the original value.

class Triple:
   def __init__(self, val):
       self._val = val
   def get_value(self):
       return self._val * 3
   def __add__(self, other):
       return self.get_value() + other.get_value()

t1 = Triple(3)
t2 = Triple(2)

print(t1 + t2)

Outputs:

15

Do the math. (33) + (22) = 9 + 6 = 15. Isn't that a magic way of working with magic methods.

More Magic Methods

  • += : 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)
  • - : object.__neg__(self) (unary -)
  • + : object.__pos__(self) (unary +)
  • 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
  • < : object.__lt__(self, other)
  • <= : object.__le__(self, other)
  • == : object.__eq__(self, other)
  • != : object.__ne__(self, other)
  • >= : object.__ge__(self, other)
  • > : object.__gt__(self, other)

Conclusion

There are a lot of magic methods in Python. It is not possible to explain them all with examples in a single article but I hope you have properly understood the concept of magic methods. If you get a chance, take a look at the official Python reference guide and keep practicing working on magic methods in Python.

Want to take to Python to the next level? Check out the top 8 places to learn Python online—from basics to advance.

And be sure to stop by the homepage to search and compare the best SDKs, APIs, and code libraries.

By Md. Sabuj Sarker | 9/27/2017 | General

{{CommentsModel.TotalCount}} Comments

Your Comment

{{CommentsModel.Message}}

Recent Stories

Top DiscoverSDK Experts

User photo
3355
Ashton Torrence
Web and Windows developer
GUI | Web and 11 more
View Profile
User photo
3220
Mendy Bennett
Experienced with Ad network & Ad servers.
Mobile | Ad Networks and 1 more
View Profile
User photo
3060
Karen Fitzgerald
7 years in Cross-Platform development.
Mobile | Cross Platform Frameworks
View Profile
Show All
X

Compare Products

Select up to three two products to compare by clicking on the compare icon () of each product.

{{compareToolModel.Error}}

Now comparing:

{{product.ProductName | createSubstring:25}} X
Compare Now