Method Resolution Order in case of Base Classes Having different init params

前端 未结 5 1216
刺人心
刺人心 2021-01-20 05:52

I am trying to understand MRO in Python. Although there are various posts here, I am not particularly getting what I want. Consider two classes A and B

5条回答
  •  庸人自扰
    2021-01-20 06:08

    As jonrsharpe mentioned at the end of his post, the best way I've come across for handling this type of situation is accepting **kwargs and extracting named arguments explicitly.

    class BaseClass(object):
        def __init__(self, **kwargs):
            print("BaseClass.__init__({},{})".format('', kwargs))
            super(BaseClass,self).__init__(**kwargs)            
    
    class A(BaseClass):
        def __init__(self, **kwargs):
            print("A.__init__({},{})".format('', kwargs))
    
            a = kwargs.pop('something')
            super(A,self).__init__(**kwargs)
    
    class B(BaseClass):
        def __init__(self, **kwargs):
            print("B.__init__({},{})".format('', kwargs))       
    
            b = kwargs.pop('anotherthing')
            super(B,self).__init__(**kwargs)
    
    
    class C(A, B):
        def __init__(self, **kwargs):
            print("C.__init__({},{})".format('', kwargs))
    
            super(C,self).__init__(**kwargs)
    
    
    c = C(something=1,anotherthing='a')
    

    Arguments that need to be extracted should be passed in named, so they appear in kwargs.

    You can even explicitly accept only named arguments by ommitting the *args as in the example, so you catch yourself with a TypeError if you forget.

    EDIT:

    After thinking on it a while I realize that my example is very specific to your example, and if you introduce another class or change inheritance it may break. There are two things that should be addressed to make this more general:

    BaseClass does not call super.

    For the example this doesn't matter, but if another class is introduced the MRO might change such that there is a class after BaseClass and it should therefore call super. This leads to the second issue:

    object.__init__() takes no parameters

    If we want to make the classes (BaseClass specifically) safe to put into a generic multiple inheritance structure where its super call might be dispatched to another class or object, we need to pop arguments off kwargs when we consume them.

    This adds another complication, though, in that it requires that no two __init__ functions share the same parameter name. I guess the takeaway is that making multiple inheritance work in a general way is difficult.

    Here is an interesting article (found through google) about some of the details: article

提交回复
热议问题