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.