Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 folowing hypothetica/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 2 + n1

Is there anyway around this? I know this example is contrived but I have an application in which it would ve 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?

like image 684
martega Avatar asked May 07 '12 23:05

martega


People also ask

Which function overloads the >> operator Python?

In Python, overloading is achieved by overriding the method which is specifically for that operator, in the user-defined class. For example, __add__(self, x) is a method reserved for overloading + operator, and __eq__(self, x) is for overloading == .

What is __ ABS __ in Python?

__abs__() → array. Calculates the absolute value for each element of an array instance (i.e., the element-wise result has the same magnitude as the respective element but has positive sign). Note. For signed integer data types, the absolute value of the minimum representable integer is implementation-dependent.

What is the correct way to overload operator?

In case of operator overloading all parameters must be of the different type than the class or struct that declares the operator. Method overloading is used to create several methods with the same name that performs similar tasks on similar data types.


2 Answers

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__
like image 143
senderle Avatar answered Oct 04 '22 03:10

senderle


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
like image 23
Marius Avatar answered Oct 04 '22 04:10

Marius