Suppose I have two classes that have methods __init__ and a third that inherits them:

 class A: def __init__ (self, x): self.x = x class B: def __init__ (self, y): self.y = y class C (A, B): def __init__ (self, **kwargs): A.__init__(self, **kwargs) B.__init__(self, **kwargs) obj = C(**{'x': 5, 'y': 10}) #TypeError: __init__() got an unexpected keyword argument 'y' 

Is it possible in some way to perform initialization without manually listing all the arguments for the two classes in the С.__init__ parameters. С.__init__ ?

  • Why do wonderful designs? Why not super().__init__(**kwargs) ? - Sergey Gornostaev
  • @SergeyGornostaev, and how to use super to get the two parent calls to work? Well, the problem with unnecessary arguments also does not solve it. - Xander
  • In parent classes, also call super . - Sergey Gornostaev

1 answer 1

The inspect module has a function getfullargspec , which for any function returns a list of its arguments. The zero element of this list is the list of required arguments. For the class method, it will first be self . Accordingly, if for the result of getfullargspec take the slice [0][:1] , then these will be the names that need to be passed to the method after self .

 from inspect import getfullargspec def filter_args(all_kwargs, func): func_kwargs = getfullargspec(func)[0][1:] return {k: v for (k, v) in all_kwargs.items() if k in func_kwargs} class A: def __init__ (self, x): self.x = x class B: def __init__ (self, y): self.y = y class C (A, B): def __init__ (self, **kwargs): a_kwargs = filter_args(kwargs, A.__init__) A.__init__(self, **a_kwargs) b_kwargs = filter_args(kwargs, B.__init__) B.__init__(self, **b_kwargs) obj = C(**{'x': 5, 'y': 10}) print(obj.x) print(obj.y) 

Or, you can change the initializers of the parent classes so that they accept everything that is passed to them and take from it only what they need:

 class A: def __init__ (self, **kwargs): self.x = kwargs['x'] class B: def __init__ (self, **kwargs): self.y = kwargs['y'] class C (A, B): def __init__ (self, **kwargs): A.__init__(self, **kwargs) B.__init__(self, **kwargs) obj = C(**{'x': 5, 'y': 10}) print(obj.x) print(obj.y)