Skip to content Skip to sidebar Skip to footer

When Should __method__ Be Called Directly?

When should a __dunder__ method be called directly? For example, instead of a + b one could write a.__add__(b) but is that a good idea?

Solution 1:

In general, no, it’s not a good idea. The operators are there for a reason after all, so when using the operator is possible, use it.

There are a few things where calling the special methods directly is useful. The most common thing would be when subclassing. So when you override a special method and you want to call the super’s method too, you will have to use the name directly.

Apart from that, having actual methods allows you to keep a reference to it, i.e. x = a.__add__. So when you would need something like that, you can use it. Granted, for the base operators it’s not that useful either, as we have the operator module which gives us binary functions for the operators already.

But there might be some edge cases. In general though: If you don’t explicitely need the method, use the operator. It’s a lot clearer.

Martijn Pieters mentioned another use case in the comments, which is avoiding calls to the inverse operator. As you may know, an expression a + b will first try to call a.__add__(b). If that returns the special value NotImplemented though, or in other words if the operator is not implemented by the type of a, then Python will try to call b.__radd__(a) instead (if b is of a different type). So in cases where you want to avoid this behavior, you could call a.__add__(b) directly—at which point you would get a NotImplemented value though.

Solution 2:

Is a.__add__(b) a good idea?

Is it easier to read? Probably not. So, generally not a good idea.

One situation where it is necessary, though, is when you're writing a subclass and need to call the a method on the parent class.

Solution 3:

Yes! There are a few use-cases I can think of:

  • Chaining to a superclass implementation:

    def__init__(self, ...):
        super().__init__(self, ...)
    
  • Calling superclass implementations to avoid an overridden method:

    def__getattribute__(self, ...):
        ...
    deffoo(self, ...):
        x = super().__getattribute__(self, 'bar')
    
  • Calling a dunder method when operators are unavailable:

    for scls in cls.__subclasses__():
        ...
    
  • Currying operators:

    mulByTen = (10).__mul__
    

In general, though, the operators are simpler and clearer.

Post a Comment for "When Should __method__ Be Called Directly?"