Python - Calling __init__ for multiple parent classes

前端 未结 2 1291
清酒与你
清酒与你 2021-01-25 18:46

Edit: I am on Python 3.

I have a class X that extends both Y and Z:

class X(Y, Z):
    def __ini         


        
相关标签:
2条回答
  • 2021-01-25 19:03

    Generally there is no other way then to call Y.__init__(self) and Z.__init__(self) directly. It's the only way to ensure that both constructors are called at least once.

    However in some weird (or normal, depending on how you look at it) cases this can lead to very unintuitive results where base constructors are called multiple times:

    class Y:
        def __init__(self):
            print('Y')
            super().__init__()
    
    class Z:
        def __init__(self):
            print('Z')
            super().__init__()
    
    class X(Y, Z):
        def __init__(self):
            print('X')
            Y.__init__(self)
            Z.__init__(self)
    
    X()
    

    Results in

    X
    Y
    Z
    Z
    

    So in that case super().__init__() in X (instead of both .__init__() calls) seems natural and will work correctly. However it will fail if Y and Z don't call super().__init__() as well. In that case you will only call one of the constructors.

    So generally there is no way to solve your issue correctly without knowing implementation of base classes.

    YARtAMI = Yet Another Reason to Avoid Multiple Inheritance

    0 讨论(0)
  • 2021-01-25 19:12

    This depends entirely on whether Y and Z were designed to work cooperatively with multiple inheritance. If they are, then you should be able to just use super:

    class X(Y, Z):
        def __init__(self):
            super().__init__()
    

    When I say that Y and Z need to be designed to work cooperatively with multiple inheritance, I mean that they must also call super in their __init__ methods:

    class Y:
        def __init__(self):
            print('Y.__init__')
            super().__init__()
    
    class Z:
        def __init__(self):
            print('Z.__init__')
            super().__init__()
    

    They should also have some strategy for handling different arguments since (particularly the constructor) of a class frequently differ in which keyword arguments that they accept. At this point, it's worth reading Super considered super! and Super considered harmful to understand some common idioms and pitfalls regarding super.

    If you don't know whether Y and Z were designed for cooperative multiple inheritance, then the safest recourse is to assume that they weren't.


    If the classes aren't designed to work with cooperative multiple inheritance, then you need to start stepping lightly (you're in dangerous waters). You can call each __init__ individually:

    class X(Y, Z):
        def __init__(self):
            Y.__init__(self)
            Z.__init__(self)
    

    But really it's probably better to not use multiple inheritance and instead choose a different paradigm (e.g. composition).

    0 讨论(0)
提交回复
热议问题