vendredi 23 avril 2021

Class Factory for classes with constructors that require different set of arguments

I am trying to perform a Class Factory (maybe not the right term to use here, not 100% sure) in which the constructors of the different classes to be instantiated through this factory may potentially have different arguments in their constructors, like so:

module.py

class A:
    def __init__(self, a=None):
        pass

    def run(self):
        pass

class B:
    def __init__(self, a=None, b=None):
        pass

    def run(self):
        pass

class C:
    def __init__(self, a=None, b=None, c=None):
        pass

    def run(self):
        pass

The problem that I am facing is how to handle the different types of arguments for the different classes to be instantiated. In the code below, if I instantiate the class with unexpected arguments we will get an exception. I know that using kwargs could solve this, but the problem using kwargs is that the list of arguments become implicit and thus the signature of the function does not fully explain what the function needs. The last example in the code below attempts to filter the incoming arguments based on the arguments of the class constructor. This would be a possible solution I think, but I was wondering if there was a design pattern or technique that could help me achieve this in a cleaner way?

example.py

import inspect
import module

# Runs OK
runner_class_name = 'C'
runner_class = getattr(module, runner_class_name)
runner_class(a=1, b=2, c=3)


# Runs KO, throws TypeError: "__init__() got an unexpected keyword argument"
runner_class_name = 'A'
runner_class = getattr(module, runner_class_name)
runner_class(a=1, b=2, c=3)


# Runs OK
runner_class_name = 'A'
runner_class = getattr(module, runner_class_name)
constructor = getattr(runner_class, '__init__')
args = inspect.getfullargspec(constructor).args
incomig_args = {'a':1, 'b':2, 'c':3}
safe_args = {k:incomig_args[k] for k in args if k in incomig_args}
runner = runner_class(**safe_args)

Thanks for any insight you could give!

Aucun commentaire:

Enregistrer un commentaire