0

I have 2 point classes with + operator overloading:

class Point2D:
    x = 0
    y = 0

    def __add__(self, __other: "Point2D"):
        return Point2D(self.x + __other.x, self.y + __other.y)

class Point3D(Point2D):
    z = 0

    def __add__(self, __other: "Point3D"):
        return Point3D(self.x + __other.x, self.y + __other.y, self.z + __other.z)

I can add 2 points of the same type, but I also want to be able to add 2 points of different types, for example:

>>> print(Point2D(1, 2) + Point3D(0, 1, 2))
(1, 3, 2)

I tried overloading the operator again with a different type expected like this (inside the Point3D class):

def __add__(self, __other: "Point2D"):
        return Point3D(self.x + __other.x, self.y + __other.y, self.z)

but it doesn't recognize them as 2 different functions and just chooses the last one (my guess is because expected type parameters are only a suggestion in python and in practice it's all just an object so it has the same function signature). Is there a way to do this without resorting to isinstance() cases inside the function?

6
  • You can only have one method with a given name in each class. It will need to use if to determine whether __other is a Point2D or Point3D and do the right hting. Commented Nov 20, 2023 at 18:44
  • a + b will always try a.__add__(b) first. b.__add__(a) only gets called if that first method call returns NotImplemented (to say "I can't handle this"). So maybe Point2D should only handle addition with other Point2Ds, then Point3D takes over in mixed cases? See docs.python.org/3/reference/… Commented Nov 20, 2023 at 18:44
  • @jonrsharpe Isn't it also possible to define Point3D.__radd__() to handle Point2D + Point3D? Commented Nov 20, 2023 at 18:46
  • @Barmar yes, but you'd still need Point2D.__add__ so say "not for me", which @OP means an isinstance check. Commented Nov 20, 2023 at 18:49
  • Good point. this question is relevant. Commented Nov 20, 2023 at 18:50

1 Answer 1

0

By creating a custom decorator you can assign different functions depending on the type. Here is a simplified example :

custom_func = {}

def ontype(_type):
    def decorated(original):
        custom_func[_type] = original
        def func(self, other):
            return custom_func[type(other)](self, other)
        return func
    return decorated

class CustomClass:
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return(str(self.value))

    @ontype(int)
    def __add__(self, other):
        return int(self.value+other)

    @ontype(float)
    def __add__(self, other):
        return float(self.value+other)

    @ontype(str)
    def __add__(self, other):
        return str(self.value)+" "+other

if __name__=="__main__":
    print(CustomClass(5)+5.0)
    print(CustomClass(5)+5)
    print(CustomClass(5)+"FIVE")

And the output is :

10.0
10
5 FIVE

As you can see here, defining multiple times the __add__ method is not getting rid of the predefined ones, thanks to the decorator. In this example I'm just putting them in a dict, but there are several ways of doing it, depends really on the usage

Sign up to request clarification or add additional context in comments.

4 Comments

Both of those additions should return a Point3D, and the addition of two Point3Ds wouldn't work correctly either.
Ok I see. I edited, maybe the new version will suits what you are looking for
i was looking for a solution without type checking inside the add function similar to how c++ does operator overloading. you can overload as many times as you want with different types expected(meaning different function signature). so for every object you want to deal with you write a different function, and when you write a + b it finds the function with the matching signature of type B parameter in the type A class.
Ok I see. I edited showing a way to decorate multiple times the function using a type, please have a look :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.