Do I Have To Override All Math Operators In A Subclass?
Solution 1:
In this case I suggest to implement your class Point2d
from scratch.
If you're lazy, take a look to some lib like sympy which includes a Point
class and other geometry stuff https://docs.sympy.org/latest/modules/geometry/index.html
Solution 2:
The problem, is that your class, when it uses any of the data model functions belonging to complex It returns a complex, so you'll need to turn this in to your Point2d
class
adding this method should do the trick
def__add__(self, b):
return Point2d(super().__add__(b))
But still there should be a better way of doing it. But this is the way to dynamically wrap some Data Model (dunder) methods.
By the way, the distance function you can make it shorter something like this
defdistanceTo(self, otherPoint):
returnabs(self - otherPoint)
Solution 3:
I'm going to mention a way of overriding all the methods without manually writing each of them, but only because we are all consenting adults here. I don't really recommend it, it is much clearer if you just override each and every operation. That said, you can write a class wrapper which inspects all the methods of the base class and converts the output to a point if it is a complex type.
import math
import inspect
defconvert_to_base(cls):
defdecorate_func(name, method, base_cls):
defmethod_wrapper(*args, **kwargs):
obj = method(*args, **kwargs)
return cls.convert(obj, base_cls) ifisinstance(obj, base_cls) else obj
return method_wrapper if name notin ('__init__', '__new__') else method
for base_cls in cls.__bases__:
for name, method in inspect.getmembers(base_cls, inspect.isroutine): # Might want to change this filtersetattr(cls, name, decorate_func(name, method, base_cls))
return cls
@convert_to_baseclassPoint2d(complex):
@classmethoddefconvert(cls, obj, base_cls):
# Use base_cls if you need to know which base class to convert.return cls(obj.real, obj.imag)
defdistanceTo(self, otherPoint):
return math.sqrt((self.real - otherPoint.real)**2 + (self.imag - otherPoint.imag)**2)
defx(self):
return self.real
defy(self):
return self.imag
p1 = Point2d(3, 3)
p2 = Point2d(6, 7)
p3 = p1 + p2
p4 = p3.distanceTo(p1)
print(p4)
# 9.219544457292887
What is happening here is that it just checks all the methods of the base class, and if what it returns is of the type of the base class, converts it to the child class, as defined by the special classmethod in the child class.
Solution 4:
In general, prefer composition to inheritance. You can implement all the desired operations in terms of complex numbers.
classPoint2D:def__init__(self, x, y):
self._p = complex(x,y)
@classmethoddef_from_complex(self, z):
return Point2D(z.real, z.imag)
def__add__(self, other):
return Point2D._from_complex(self._p + other._p)
# etc
Is it a lot of boilerplate? Yes. But it's not really boilerplate you can avoid.
Post a Comment for "Do I Have To Override All Math Operators In A Subclass?"