0

I am trying to write an __init__ method for a class such that all the classes it derives from get the same set of keyword arguments. Let's say,

class First(object):

    def __init__(self, *args, **kwargs):
        super(First, self).__init__()
        print('First', kwargs)

class Second(object):

    def __init__(self, *args, **kwargs):
        super(Second, self).__init__()
        print('Second', kwargs)

class Third(First, Second):

    def __init__(self, *args, **kwargs):
        super(Third, self).__init__(*args, **kwargs)
        print('Third', kwargs)

If I instantiate Third with a bunch of keywords, I can see that they all get "taken out" by the __init__ method of First,

In [5]: tc = Third(key='value', someother='nothing')
Second {}
First {'key': 'value', 'someother': 'nothing'}
Third {'key': 'value', 'someother': 'nothing'}

I understand that this is the expected behavior, so I'm not complaining. However, is there a way to write this class hierarchy such that both First and Second get the same set of kwargs? More generally, I'd like to write the hierarchy such that if Third derives from N classes, all N of those should get the same set of kwargs unless one of the explicitly pops one of the keys.

I have looked at other questions such as this one, and answers have pointed out that that's not the default beahviour. I get that. But, is there a way to do it?

TM5
  • 192
  • 3
  • 12
  • 2
    `super` is designed for *cooperative* inheritance. If you want to inherit from `First` and `Second`, either both must be designed to work when they aren't necessarily the last class in the MRO, or you need to inherit from adaptor classes based on `First` and `Second`. – chepner Jul 06 '23 at 14:20
  • 1
    Put another way, neither `First` nor `Second` can assume that `super().__init__()` is going to call `object.__init__`. – chepner Jul 06 '23 at 14:20
  • 1
    In fact, in cooperative classes, `__init__` should use the named args it knows and pass everything else to its parent. – Serge Ballesta Jul 06 '23 at 14:29
  • 1
    Indeed: one should read https://rhettinger.wordpress.com/2011/05/26/super-considered-super/ for advice on *properly* designing classes intended for cooperative multiple inheritance (and specifically for defining `__init__` in such classes). – chepner Jul 06 '23 at 14:31
  • 1
    `object.__init__` doesn't even do anything anyway, so there's no point calling it except in the situation described in the linked blog post. – wjandrea Jul 06 '23 at 15:55
  • In short, accept arbitrary keyword arguments, *remove* the ones that you *know* aren't expected by any other class, and pass on the rest. – chepner Jul 06 '23 at 16:08

0 Answers0