Reputation: 5831
I am trying to understand how operator overriding works for two operands of a custom class.
For instance, suppose I have the following:
class Adder:
def __init__(self, value=1):
self.data = value
def __add__(self,other):
print('using __add__()')
return self.data + other
def __radd__(self,other):
print('using __radd__()')
return other + self.data
I initialize the following variables:
x = Adder(5)
y = Adder(4)
And then proceed to do the following operations:
1 + x
using __radd__()
Out[108]: 6
x + 2
using __add__()
Out[109]: 7
The two operations above seem straigtforward. If a member of my custom class is to the right of the "+" in the addition expression, then __radd__
is used. If it is on the left, then __add__
is used. This works for expressions when one operand is of the Adder
type and another one is something else.
When I do this, however, I get the following result:
x + y
using __add__()
using __radd__()
Out[110]: 9
As you can see, if both operands are of the custom class, then both __add__
and __radd__
are called.
My question is how does Python unravel this situation and how is it able to call both the right-hand-addition function, as well as the left-hand-addition function.
Upvotes: 0
Views: 80
Reputation: 78556
That's the because the implementation of your __add__
and __radd__
method do not give any special treatment to the instances of the Adder
class. Therefore, each __add__
call leads to an integer plus Adder instance operation which further requires __radd__
due to the Adder instance on the right side.
You can resolve this by doing:
def __add__(self, other):
print('using __add__()')
if isinstance(other, Adder):
other = other.data
return self.data + other
def __radd__(self, other):
print('using __radd__()')
return self.__add__(other)
Upvotes: 1
Reputation: 599610
It's because inside your methods you add the data to other
. This is itself an instance of Adder. So the logic goes:
__add__
on x;x.data
(an int) to y (an Adder instance)__radd__
method, so__radd__
on y;y.data
(another int).Usually you would check to see if other
was an instance of your class, and if so add other.data
rather than just other
.
Upvotes: 1