34

I'm just diving into some more advanced python subjects (well, advanced to me at least). I am now reading about multiple inheritance and how you can use super(). I more or less understand the way the super function is used, but (1) What's wrong with just doing it like this?:

class First(object): def __init__(self): print "first" class Second(object): def __init__(self): print "second" class Third(First, Second): def __init__(self): First.__init__(self) Second.__init__(self) print "that's it" 

On to super(), Andrew Kuchlings paper on Python Warts says:

usage of super() will also be correct when the Derived class inherits from multiple base classes and some or all of them have init methods

So I rewrote the example above as follows:

class First(object): def __init__(self): print "first" class Second(object): def __init__(self): print "second" class Third(First, Second): def __init__(self): super(Third, self).__init__(self) print "that's it" 

This however, only runs the first init it can find, which is in First. (2) Can super() be used to run both the init's from First and Second, and if so, how? Running super(Third, self).__init__(self) twice just runs First.init() twice..

To add some more confusion. What if the inherited classes' init() functions take different arguments. For example, what if I had something like this:

class First(object): def __init__(self, x): print "first" class Second(object): def __init__(self, y, z): print "second" class Third(First, Second): def __init__(self, x, y, z): First.__init__(self, x) Second.__init__(self, y, z) print "that's it" 

(3) How would I be able to supply the relevant arguments to the different inherited classes init functions using super()?

All tips are welcome!

ps. Since I have several questions I made them bold and numbered them..

1
  • super(Class, self) returns an object, so you shouldn't call it with .__init__(self), but just .__init__(). You can see this in the answers, but your original first code returns exception TypeError: __init__() takes exactly 1 argument (2 given). Commented May 28, 2014 at 5:47

2 Answers 2

13

For question 2, you need to call super in each class:

class First(object): def __init__(self): super(First, self).__init__() print "first" class Second(object): def __init__(self): super(Second, self).__init__() print "second" class Third(First, Second): def __init__(self): super(Third, self).__init__() print "that's it" 

For question 3, that can't be done, your method needs to have the same signature. But you could just ignore some parameters in the parent clases or use keywords arguments.

Sign up to request clarification or add additional context in comments.

10 Comments

So you mean the use of super() is dependent on the use of super() in the inherited classes? What if I do not control the inherited classes? Would I then simply do First.__init__(self) and Second.__init__(self) like in my first example?
Yes, "super" is a cooperative process, all classes needs to use the mechanism or it just doesn't works. You can find a bit more info here: rhettinger.wordpress.com/2011/05/26/super-considered-super And yes, if a class in the hierarchy doesn't use super, I think you have to use the "old style" way :)
Thanks for that. Just one last question; why is super() added to the language anyway? What's the advantage of it over the "old style"?
I see two advantages: you don't have to explicitly reference the parent class and in case of multiple inheritance you don't have to call multiple parent constructors... also in python3, you only have to call super().something() instead of super(Class, self).something()
You say: "in case of multiple inheritance you don't have to call multiple parent constructors". I don't understand that though, because if I call super(CurrentClass, self).__init__() (as I do in my second piece of code) it only runs the init function of the first inherited class instead of the init of all inherited classes. So that means that super() cannot be used when doing multiple inheritance.. right?
|
3

1) There is nothing wrong in doing like what u have done in 1, if u want to use the attributes from base class then u have to call the base class init() or even if u r using methods from base class that uses the attributes of its own class then u have to call baseclass init()

2) You cant use super to run both the init's from First and Second because python uses MRO (Method resolution order)

see the following code this is diamond hierarchy

class A(object): def __init__(self): self.a = 'a' print self.a class B(A): def __init__(self): self.b = 'b' print self.b class C(A): def __init__(self): self.c = 'c' print self.c class D(B,C): def __init__(self): self.d = 'd' print self.d super(D, self).__init__() d = D() print D.mro() 

It prints:

d b [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>] 

MRO of python would be D,B,C,A

if B does't have init method it goes for C.

3) You can't do it all methods need to have same signature.

1 Comment

I don't think it is a good design for Python. You have to have a class' init's signature be kept the same as other init signatures from some irrelevant sibling class. This conflicts with modularity.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.