A metaclass that stores the concrete __init__
parameters in a class field:
class ParameterReader(ABCMeta):
def __init__(cls, *args, **kwargs):
parameters = inspect.signature(cls.__init__).parameters
parameters = {key: value for key, value in parameters.items() if key not in ['self', 'args', 'kwargs']}
try:
cls._init_parameters = cls.__bases__[0]._init_parameters.copy()
cls._init_parameters.update(parameters)
except AttributeError:
cls._init_parameters = parameters
super().__init__(*args, **kwargs)
_init_parameters
can then be used within the class instance or outside of it:
class Fruit(metaclass=ParameterReader):
def __init__(self, color):
print(color)
class Corn(Fruit):
def __init__(self, size, *args, **kwargs):
super().__init__(*args, **kwargs)
print(size)
print(self._init_parameters)
print(Corn._init_parameters)
Producing:
{'color': <Parameter "color">, 'size': <Parameter "size">}
As well as in instantiation:
Corn(10, 'yellow')
Producing:
yellow
10
{'color': <Parameter "color">, 'size': <Parameter "size">}
Note how this handles using *args
, **kwargs
in Corn's __init__ parameters.
Also, note the naming difference between arguments and parameters.
__init__
gets called. See this answer https://mcmap.net/q/37833/-why-is-__init__-always-called-after-__new__ – Circumscribe