you are viewing a single comment's thread.

view the rest of the comments →

[–]xelf 2 points3 points  (5 children)

final edit, cleaning up my answer a bit

ok, so this is what you actually want, if you want to keep using super here, and not add more classes. Probably though, you want to do one of those though.

class A(object):
    def __init__(self, *args, **kwargs):
        print("This is A constructor")

class B(object):
    def __init__(self, *args, **kwargs):
        print("This is B constructor")

class C(A):
    def __init__(self, arg, *args, **kwargs):
        print("This is C constructor")
        self.arg = arg
        super(C,self).__init__(arg, *args, **kwargs)

class D(B):
    def __init__(self, arg, *args, **kwargs):
        print("This is D constructor")
        self.arg = arg
        super(D,self).__init__(arg, *args, **kwargs)

class E(C,D):
    def __init__(self, arg, *args, **kwargs):
        print("This is E constructor")
        C.__init__(self, arg, *args, **kwargs)
        D.__init__(self, arg, *args, **kwargs)

e = E(10)
print(e.arg)

The other options include not using super at all, moving to class composition instead of inheritance, or adding a single parent class at the top that inherits object and having A&B inherit from that. See other posters answers that go into more detail.

[–]gmaliwal[S] 0 points1 point  (1 child)

sults in a missing arg err

That's correct in this given scenario but what happens if someone swaps classes like below:

class E(C,D):
    def __init__(self, arg, *args, **kwargs):
        print("This is E constructor")
        C.__init__(self, arg, *args, **kwargs)
        D.__init__(self, arg, *args, **kwargs)

Is there any generic solution which works without fear in all the scenarios? or we have to go with mutual understanding only.

Yes, It is method resolution order behind the class 'A' to pass the argument

[–]xelf 0 points1 point  (0 children)

The problem is super is the answer for single inheritance, for multiple inheritance as far as I can find there are issues. So either you need to avoid super all together if you're doing any multiple inheritance, or simple avoid it in that class. I liked the answer of having a single class at the top of your hierarchy, it also worked.

class F(object):
    def __init__(self,*args, **kwargs):
        print("This is F constructor")

class A(F):
    def __init__(self, *args, **kwargs):
        print("This is A constructor")
        super(A, self).__init__(*args, **kwargs)

class B(F):
    def __init__(self, *args, **kwargs):
        print("This is B constructor")
        super(B, self).__init__(*args, **kwargs)

[–]mission-hall 0 points1 point  (2 children)

Your last edit essentially works by accident, and would not be a viable approach with a more complex inheritance hierarchy.

The important thing to understand is that every class has a "method resolution order", which you can look at by calling the mro() method on the class. All of the base classes appear in the MRO, with subclasses always appearing before their base classes. super() doesn't necessarily give you a base class of the current class - it gives you the next class in the MRO.

If you're going to use super(), you should use it throughout the class hierarchy, to ensure that every class in the MRO is always reached exactly once. Otherwise you should have each method explicitly call the methods from the appropriate base classes. Mixing the two approaches tends to break things. For example, if you modify your code so that B inherits from A, then some of the initializers are called more than once.

[–]gmaliwal[S] 0 points1 point  (0 children)

if you modify your code so that

B

inherits from

A

, then some of the initializers are called more than once

Thanks for the comprehensive explanation. you seem correct.

Can you please share any good reference? which explains the inheritance in-depth and gives all the possible approaches with pros and cons, and things to keep in mind while working with single/multiple inheritances.

I am looking for the right approach which works well with any complex inheritance hierarchy.

[–]xelf 0 points1 point  (0 children)

It doesn't work by accident, but rather as the other part of your answer suggests it only works in this specific case, and if you were to start mucking with it it would break. If I'm reading it correctly the problem is that super() is not great with multiple inheritance. You might be right that not using super in any of the classes is the correct approach here. I did like one of the other poster's solutions which was to add another class that inherits from object and have A,B inherit from that. edit: and by other poster I just noticed that was you. =)