Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

User defined int class that supports addition

I want to create a class that wraps an int and allows some things not normally allowed with int types. Here is my code:

class tInt(int):
    def __add__(self, other):
        if type(other) == str:
            return str(self) + str(other)
        elif type(other) == int:
            return int(self) + other
        elif type(other) == float:
            return float(self) + float(other)
        else:
            return self + other
a = tInt(2)
print (a + "5")
print ("5" + a)

The output was.

>> 25
Traceback (most recent call last):
  File "C:\example.py", line 14, in <module>
    print ("5" + a)
TypeError: Can't convert 'tInt' object to str implicitly

So, the first print statement ran nicely, and gave what I expected, but the second one gave an error. I think this is because the first one is using tInt's add function because a appeared before + "5" and the second one used the string "5"'s add function first because it appeared first. I know this but I don't really know how to either force a's add function or allow the tInt class to be represented as a string/int/etc.. when a normal type appears before it in an operation.

like image 942
tatatat0 Avatar asked Apr 20 '16 13:04

tatatat0


1 Answers

You need to implement an __radd__ method to handle the case when an instance of your class is on the right hand side of the addition.

The docs say:

These methods are called to implement the binary arithmetic operations (+, -, *, @, /, //, %, divmod(), pow(), **, <<, >>, &, ^, |) with reflected (swapped) operands. These functions are only called if the left operand does not support the corresponding operation and the operands are of different types. For instance, to evaluate the expression x - y, where y is an instance of a class that has an __rsub__() method, y.__rsub__(x) is called if x.__sub__(y) returns NotImplemented.

Example:

class tInt(int):

    def __add__(self, other):
        if isinstance(other, str):
            return str(self) + str(other)
        elif isinstance(other, int):
            return int(self) + other
        elif isinstance(other, float):
            return float(self) + float(other)
        else:
            return NotImplemented

    def __radd__(self, other):
        return self.__add__(other) 

a = tInt(2)
for x in ["5", 5, 5.0]:
    print (a + x)
    print (x + a)

25
25

7
7

7.0
7.0

As @chepner pointed out in the comments, returning NotImplemented for cases that your method doesn't handle will cause Python to try other ways of performing the operation, or raise a TypeError if there is no way to perform the requested operation.

In the above code, the implementation of __radd__ is trivial because integer addition is associative, that is

2 + 3 == 3 + 2

Addition of other types may not be associative, in which case __radd__ will need to do more than just delegate to __add__:

'a' + 'b' != 'b' + 'a'
[0, 1] + [2, 3] != [2, 3] + [0, 1]
like image 50
snakecharmerb Avatar answered Oct 25 '22 06:10

snakecharmerb