Reputation: 366
I am using python 3 (3.3, but I'm interested of any nice solution, even if it's only python 3.4 or more). I want to create a custom class with conditional overloading operator like that:
class test :
def __init__(self,overload) :
if overload :
self.__add__=lambda x,y : print("OK")
self.f=lambda : print(True)
def f(self) : print(False)
t=test(False)
t.f() #print False as expected
u=test(True)
u.f() #print True as expected
u+u #fails as if it was not implemented
After some digging, I realized that operator +
does not call __add__
on the object, but on the class. Hence, I can't do it like that (or can I)?
So I can define something like that :
class test :
def __init__(self,overload) :
self.overload=overload
def __add__(self,other) :
if self.overload : print("OK")
else #FAILURE
def f(self) : print(self.overload)
But what can I put into the FAILURE
statement such that it fails exactly like if it was not implemented? For example, if it fails, I'll be happy if it tried __radd__
on the second operator.
Upvotes: 2
Views: 614
Reputation: 1121436
Indeed, special methods are looked up on the type and you cannot set them on the instance.
If you want to not always support .__add__
return the NotImplemented
singleton:
class test:
def __init__(self, overload):
self.overload = overload
def __add__(self, other):
if not self.overload:
return NotImplemented
print("Ok")
Returning NotImplemented
from a rich comparison method makes Python behave as if there was no such method; usually this is used to signal that the type of other
isn't supported, but you are free to return it when you don't want to support the operation just now.
Note that Python will still try the reverse operation; for test() + something
, Python first tries test().__add__(something)
, then something.__radd__(test())
is called if the first operation returned NotImplemented
. If the latter doesn't exist or also returns NotImplemented
, a TypeError
is raised.
Demo:
>>> class test:
... def __init__(self, overload):
... self.overload = overload
... def __add__(self, other):
... if not self.overload:
... return NotImplemented
... print("Ok")
...
>>> test(False) + 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'instance' and 'int'
>>> test(True) + 1
Ok
Upvotes: 5