martega
martega

Reputation: 2143

Operator overloading in python with the object on the right hand side of the operator

I recently learned about operator overloading in python and I would like to know if the following is possible.

Consider the following hypothetical/contrived class.

class My_Num(object):
    def __init__(self, val):
        self.val = val

    def __add__(self, other_num):
        if isinstance(other_num, My_Num):
            return self.val + other_num.val
        else:
            return self.val + other_num

I know that the way that's written above, I can do things like this

n1 = My_Num(1)
n2 = My_Num(2)
n3 = 3
print n1 + n2
print n1 + n3

and those will work as expected. I also know that the way it's currently written I can't do this

n1 = My_Num(1)
n2 = 2
print n2 + n1

Is there any way around this? I know this example is contrived but I have an application in which it would be very useful if when I did operator overloading, the class for which I define the operator can appear on the right hand side of operator. Is this possible in python?

Upvotes: 20

Views: 6591

Answers (2)

senderle
senderle

Reputation: 151157

Yes. For example, there is __radd__. Also, there are none for __le__(), __ge__(), etc., but as Joel Cornett rightly observes, if you define only __lt__, a > b calls the __lt__ function of b, which provides a workaround.

>>> class My_Num(object):
...     def __init__(self, val):
...         self.val = val
...     def __radd__(self, other_num):
...         if isinstance(other_num, My_Num):
...             return self.val + other_num.val
...         else:
...             return self.val + other_num
... 
>>> n1 = My_Num(1)
>>> n2 = 3
>>> 
>>> print n2 + n1
4
>>> print n1 + n2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'My_Num' and 'int'

Note that in at least some cases it's reasonable to do something like this:

>>> class My_Num(object):
...     def __init__(self, val):
...         self.val = val
...     def __add__(self, other_num):
...         if isinstance(other_num, My_Num):
...             return self.val + other_num.val
...         else:
...             return self.val + other_num
...     __radd__ = __add__

Upvotes: 17

Marius
Marius

Reputation: 60210

You have to overload the __radd__ method (right-side addition). Your function should look pretty much the same as your __add__ method, e.g.:

def __radd__(self, other):
     return self.val + other.val

Upvotes: 2

Related Questions