EDIT #1: I have updated the example with a "manual" if/else based solution as suggested to demonstrate the need for further automation.
How to efficiently dispatch functions (i.e. implement something like multimethods) where the target function is selected based on keyword argument names instead of types?
My use case for this is implementing multiple factory methods for dataclasses whose fields are inter-dependent and which can be initialized based on different subsets of these fields e.g.
Below is an example using recursion that works fine but requires lots of hand-written error-prone code and doesn't really scale to more complex cases.
def a_from_b_c(b, c):
return b+c
def b_from_a_c(a, c):
return a+c
def c_from_a_b(a, b):
return a**b
@datalass
class foo(object):
a: float
b: float
c: float
@classmethod
def init_from(cls, **kwargs):
if "a" not in kwargs and all(k in kwargs for k in ("b", "c")):
kwargs["a"] = a_from_b_c(kwargs["b"], kwargs["c"])
cls.init_from(**kwargs)
if "b" not in kwargs and all(k in kwargs for k in ("a", "c")):
kwargs["b"] = b_from_a_c(kwargs["a"], kwargs["c"])
cls.init_from(**kwargs)
if "c" not in kwargs and all(k in kwargs for k in ("a", "b")):
kwargs["c"] = c_from_a_b(kwargs["a"], kwargs["b"])
cls.init_from(**kwargs)
return cls(**kwargs)
I am searching for a solution that scales up to dataclasses with many fields and complex initialization paths while on the other hand requiring less hand-written code with lots of duplications and sources of errors.. the patterns in the code above are quite obvious and could be automated, but I want to be sure to use the right tools here.