Dunder Method - Special Methods

What is dunder method

  • A method with 2 underscores around it like_this is called as "double underscore method" i.e. dunder method, which is not an official term.
  • Officially these are called as "special methods" or as "magic method" in some cases
  • They act as "hook", allowing us to customize the behaviour of built in Python functions

Definition in classes

  • This depends on whether we are inheriting a class or defining our own functions inside a class
  • init - initializer method
  • repr - this is developer focused string representation

  • eq - this method can give our objects a nice sense of equality

  • iter - this method if our objects support unpacking

Calling dunder methods for Objects

  • We should implement dunder methods on our objects but should not call dunder methods on other objects
  • They should be implemented by us and called by Python
  • Instead of calling dunder methods it is better to use higher level operations that are powered by those dunder methods """ from datetime import date from pathlib import Path path = Path.cwd() today = date.today() """

  • If we want to convert these objects to strings, we could call the str method on these objects: """ path_string = path.str() date_string = today.str() path_string '/home/trey' date_string '2024-01-17' """

  • But we're not supposed to do that! We're meant to pass those objects to the built-in str function: """ path_string = str(path) date_string = str(today) """ The same applies for every other dunder method.

  • We should use the len function to get an object's length, not the len method: """ my_collection.len() # no len(my_collection) # yes """

Why not call the dunder method

  • But there's another reason you shouldn't call dunder methods: there's not a one-to-one relationship between dunder methods and the features they empower. Sometimes calling dunder methods won't be nearly as straightforward as using a corresponding higher-level Python feature.
  • For example, if we want to divide one number by another, we could use the / operator or we could use the truediv method: """ n = 10 m = 2 n / m 5.0 n.truediv(m) 5.0 """
  • But while the / operator will always give us the expected answer, the truediv will not: """ m = 2.5 n / m 4.0 n.truediv(m) NotImplemented """
  • Integers don't know how to interact with floating point numbers, so when using the / operator between an integer and a floating point number, Python needs to ask the floating point number to divide the integer by itself. It does this by using its rtruediv method: """ m.rtruediv(n) 4.0 """

Sometimes we need to call dunder methods

  • In case if we are implementing custom methods inside the class then we will have to call the dunder method in that case

Avoid calling dunder method but do define them

  • We should avoid calling them because -
  • There's not always a one-to-one relationship between high-level operations and individual dunder methods
  • Dunder method calls signals that something low-level is happening
  • There's usually a higher-level way to do the same thing that looks friendlier

  • If we want to achieve something at a low level then yes we should call them otherwise for high level programming we should avoid using them.