I would like to decorate the shapely.geometry.Point
class to instantiate it from a dendropy.datamodel.basemodel.AnnotationSet
object. I chose the multimethod
package to dispatch __init__
of the superclass as it dispatches this method into a simple class without any problems:
from multimethod import multimeta
class Example(metaclass=multimeta):
def __init__(self, *args, **kwargs):
print("DEFAULT")
def __init__(self, x: str):
print("Initialising from a string")
def __init__(self, x: int):
print("Initialising from an integer")
However, it does not work in my case with the inheritance:
class Point(Point, metaclass=multimeta):
def __init__(self, annotations: AnnotationSet):
try:
super().__init__(
float(annotations.get_value(LONGITUDE_ALIAS)),
float(annotations.get_value(LATITUDE_ALIAS)),
)
except (TypeError, ValueError):
raise ValueError(
f"There is no coordinates in the annotations:\n{annotations}"
)
It initialises from AnnotationSet
but not from default arguments:
Point(6, 4)
---------------------------------------------------------------------------
DispatchError Traceback (most recent call last)
Cell In [461], line 1
----> 1 Point(6, 4)
File ~\anaconda3\envs\bioinfo\lib\site-packages\multimethod\__init__.py:313, in multimethod.__call__(self, *args, **kwargs)
311 if self.pending: # check first to avoid function call
312 self.evaluate()
--> 313 func = self[tuple(func(arg) for func, arg in zip(self.type_checkers, args))]
314 try:
315 return func(*args, **kwargs)
File ~\anaconda3\envs\bioinfo\lib\site-packages\multimethod\__init__.py:307, in multimethod.__missing__(self, types)
305 return self.setdefault(types, *funcs) # type: ignore
306 msg = f"{self.__name__}: {len(keys)} methods found" # type: ignore
--> 307 raise DispatchError(msg, types, keys)
DispatchError: ('__init__: 0 methods found', (<class '__main__.Point'>, <class 'int'>), [])
Are there ways to dispatch the superclass methods? I am not interested in multimethod
specifically; maybe there is any way besides?
This is a paraphrase of Coady's answer with their consent.
To dispatch a supermethod, we need to specify it manually, wrapping it into a multimethod
instance & using the register
method as a decorator for the first of new multimethods. For instance, in my case:
class Point(Point):
@multimethod(Point.__init__).register
def __init__(self, annotations: AnnotationSet):
try:
super().__init__(
float(annotations.get_value(LONGITUDE_ALIAS)),
float(annotations.get_value(LATITUDE_ALIAS)),
)
except (TypeError, ValueError):
raise ValueError(
f"There is no coordinates in the annotations:\n{annotations}"
)