Calling super() with arguments set in sub-class __init__()?

95 Views Asked by At

So I have a class (let's call it ParamClass) which requires a parameter for initialization, and that parameter is something that should be available to the user to configure via some option-setting interface.

ParamClass knows nothing about the configuration interface or how to read them. So I made another class, called Configurator, which does all of that. When a class inherits from Configurator and tells it what configuration keys to read, Configurator's __init__() method will read those keys and assign their values to the correct attributes in self.

The problem I run into, however, is that when I try to pass arguments to super(), including the parameters to be read by Configurator, those parameters have no value yet. But they are passed as constants in the argument list to the super(). Example shown below. MyClass.__init__() can't even get started because self.server_param doesn't exist yet.

class ParamClass:
    """Just some class that needs a parameter for init"""
    def __init__(self, param1, **kwargs) -> None:
        super().__init__(**kwargs)
        self.value = param1


class Configurator:
    """Reads parameters from a configuration source and sets appropriate class 
       variables.
    """
    def __init__(self, **kwargs) -> None:
        super().__init__(**kwargs)
        self.server_param = 2


class MyClass(Configurator, ParamClass):
    def __init__(self, **kwargs) -> None:
        super().__init__(param1=self.server_param, **kwargs)  
            # <-- Gives AttributeError: 'MyClass' object has no attribute 'server_param'

MyClass()

The only way I can get this to work is to break MRO in Configurator.init() and force the order of initilization. This is bad for obvious reason - I plan to use Configurator throughout my code and can't break MRO with it.

class ParamClass:
    """Just some class that needs a parameter for init"""
    def __init__(self, param1, **kwargs) -> None:
        super().__init__(**kwargs)
        self.value = param1


class Configurator:
    """Reads parameters from a configuration source and sets appropriate class 
       variables.
    """
    def __init__(self, **kwargs) -> None:
        # super().__init__(**kwargs)
        self.server_param = 2


class MyClass(Configurator, ParamClass):
    def __init__(self,  **kwargs) -> None:
        Configurator.__init__(self, **kwargs)  
            # <-- After this call, self.server_param is defined.
        ParamClass.__init__(self, param1=self.server_param, **kwargs)


MyClass()

How do I accomplish configuration of parameters in while user super? How do I do this in a generalized way that doesn't require Configurator to know little details about ParamClass?

Note: In my particular case, I don't "own" the ParamClass() code. It is library code that I'm using.

0

There are 0 best solutions below