tatatat0 tatatat0 - 7 months ago 7
Python Question

Automatic type conversions of user defined classes

So what I want to do is create a class that wraps an int and allows some things not normally allowed with int types. I don't really care if its not pythonic or w/e I'm just looking for results. 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.

Answer

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. 2 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.