Can You Impose Object Precedence For Overloaded Operators In Python?
Solution 1:
There's no builtin mechanism for defining a "precedence" as you describe. What you could do is implement the precedence checking yourself within the magic methods. That is, you could define the object's __add__ method so that it checks the "precedence" of the other object (however that's defined), and calls that object's __add__ (or __radd__) if its precedence is higher.
Note that, if you just want the LHS __add__ to defer to the RHS __radd__ you can return NotImplemented, which will essentially tell Python "act as if the __add__ method you just called didn't exist".
Here is a sketch of how this could be done with a decorator on the magic methods:
defdeco(op):
defnewOp(self, other):
if other.precedence > self.precedence:
returnNotImplementedreturn op(self, other)
return newOp
classThing(object):
precedence = 0def__init__(self, val):
self.val = val
@decodef__add__(self, other):
print"Called", self, "__add__"return self.__class__(self.val + other.val)
def__radd__(self, other):
print"Called", self, "__radd__"return self.__class__(self.val + other.val)
classWeak(Thing):
precedence = 1classStrong(Thing):
precedence = 2This results in the Strong version always being called regardless of the order of operands, so it always returns a Strong:
>>> Weak(1) + Strong(1)
Called <__main__.Strongobject at 0x01F96BF0> __radd__
<__main__.Strongobject at 0x01F96BD0>
>>> Strong(1) + Weak(1)
Called <__main__.Strongobject at 0x01F96B90> __add__
<__main__.Strongobject at 0x01F96250>
Solution 2:
Python will use __radd__ if __add__ is not implemented on the first of the items using the + operator.
foo + bar
will attempt to use foo's __add__ operator on the other, bar. If that is not implemented, it will call bar's __radd__.
classFoo(object):
passclassBar(object):
def__radd__(self, other):
print('Bar.__radd__ was called!')
>>> foo = Foo()
>>> bar = Bar()
>>> foo + bar
Bar.__radd__ was called!
And when Foo has __add__ it gets precedence:
classFoo(object):
def__add__(self, other):
print('Foo.__add__ was called!')
>>> foo = Foo()
>>> foo + bar
Foo.__add__ was called!
You cannot force Python to do anything special if both are implemented, the order of precedence is predefined. You can check for the other's existence however:
classFoo(object):
def__add__(self, other):
ifhasattr(other, '__radd__'):
return other.__radd__(self)
else:
print('Foo.__add__ was called!')
>>> foo = Foo()
>>> foo + bar
Bar.__radd__ was called!
Post a Comment for "Can You Impose Object Precedence For Overloaded Operators In Python?"