Overload All Arithmetic Operators In Python
Solution 1:
What about this?
class MyFancyNumber(int):
def __new__(cls, num, info=None):
return super(MyFancyNumber, cls).__new__(cls, num)
def __init__(self, num, info=None):
self.num = num
self.info = info
>>> MyFancyNumber(5)
5
>>> MyFancyNumber(5) + 2
7
>>> MyFancyNumber(5) / 4
1
>>> MyFancyNumber(5) * 0.5
2.5
>>> MyFancyNumber(5) - 7
-2
>>> MyFancyNumber(5, 'info').info
'info'
I guess based on the above, you can figure out what you need.
Solution 2:
I don't endorse this as being particularly idiomatic, but...
Assuming all of your function definitions behave identically, like "just invoke the base behavior of the self.num
class and apply all the non-self arguments to it", then you can loop through all the function names you want to define, and create each one using setattr
. Example:
class MyFancyNumber(object):
def __init__(self, num, info):
self.num = num
self.info = info
def __repr__(self):
return "MyFancyNumber({}, {})".format(repr(self.num), repr(self.info))
def make_func(name):
return lambda self, *args: MyFancyNumber(getattr(self.num, name)(*args), self.info)
for name in ["__add__", "__sub__", "__mul__", "__div__", "__invert__", "__neg__", "__pos__"]:
setattr(MyFancyNumber, name, make_func(name))
x = MyFancyNumber(50, "hello")
print(x + 10)
print(x - 10)
print(x * 10)
print(x / 10)
print(~x)
print(-x)
print(+x)
Result:
MyFancyNumber(60, 'hello')
MyFancyNumber(40, 'hello')
MyFancyNumber(500, 'hello')
MyFancyNumber(5, 'hello')
MyFancyNumber(-51, 'hello')
MyFancyNumber(-50, 'hello')
MyFancyNumber(50, 'hello')
Edit: I wasn't sure whether you wanted the result of arithmetic to be a MyFancyNumber or a regular built-in numerical type, but either way, the implementation is pretty similar:
class MyFancyNumber(object):
def __init__(self, num, info):
self.num = num
self.info = info
def __repr__(self):
return "MyFancyNumber({}, {})".format(repr(self.num), repr(self.info))
def make_func(name):
return lambda self, *args: getattr(self.num, name)(*args)
for name in ["__add__", "__sub__", "__mul__", "__div__", "__invert__", "__neg__", "__pos__"]:
setattr(MyFancyNumber, name, make_func(name))
x = MyFancyNumber(50, "hello")
print(x + 10)
print(x - 10)
print(x * 10)
print(x / 10)
print(~x)
print(-x)
print(+x)
Result:
60
40
500
5
-51
-50
50
Solution 3:
No, you have to define all the arithmetic operators otherwise how would Python know what to do with them. Don't forget you also need the reverse operators like __radd__
.
Also the code you've written returns an int
for x+1
. Did you mean that or did you want adding a fancy number to return another fancy number?
You could just subclass int
or float
. Then you don't have to reimplement the operators but you'll still lose the special nature whenever you operate on a value.
A better solution would just be to have the numeric value in an attribute and convert to numbers explicitly when that's what you want. You can use __int__()
and __float__()
to implement the conversion.
The documentation covers what you need to do if you really do want to emulate a numeric type: for Python 3.x https://docs.python.org/3/reference/datamodel.html?highlight=int#emulating-numeric-types or for Python 2.x https://docs.python.org/2/reference/datamodel.html?highlight=int#emulating-numeric-types
Solution 4:
This works for me in python 2.7 as long as you pass just one argument in the init. Sadly have no idea why it works though.
class MyFancyNumber(int):
def __init__(self, num):
self.num = num # the actual number
def add_info(self,info):
self.info = info ## Add the info separately
def doFancyStuff(self):
# does something fancy
print MyFancyNumber(5)+5
Usage
f = MyFancyNumber(2)
f.add_info(info)
f+4 ## returns 6
Post a Comment for "Overload All Arithmetic Operators In Python"