How does Python's "super" do the right thing? How does Python's "super" do the right thing? python python

How does Python's "super" do the right thing?


Change your code to this and I think it'll explain things (presumably super is looking at where, say, B is in the __mro__?):

class A(object):    def __init__(self):        print "A init"        print self.__class__.__mro__class B(A):    def __init__(self):        print "B init"        print self.__class__.__mro__        super(B, self).__init__()class C(A):    def __init__(self):        print "C init"        print self.__class__.__mro__        super(C, self).__init__()class D(B, C):    def __init__(self):        print "D init"        print self.__class__.__mro__        super(D, self).__init__()x = D()

If you run it you'll see:

D init(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)B init(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)C init(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)A init(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)

Also it's worth checking out Python's Super is nifty, but you can't use it.


I have provided a bunch of links below, that answer your question in more detail and more precisely than I can ever hope to. I will however give an answer to your question in my own words as well, to save you some time. I'll put it in points -

  1. super is a builtin function, not an attribute.
  2. Every type (class) in Python has an __mro__ attribute, that stores the method resolution order of that particular instance.
  3. Each call to super is of the form super(type[, object-or-type]). Let us assume that the second attribute is an object for the moment.
  4. At the starting point of super calls, the object is of the type of the Derived class (say DC).
  5. super looks for methods that match (in your case __init__) in the classes in the MRO, after the class specified as the first argument (in this case classes after DC).
  6. When the matching method is found (say in class BC1), it is called.
    (This method should use super, so I am assuming it does - See Python's super is nifty but can't be used - link below)That method then causes a search in the object's class' MRO for the next method, to the right of BC1.
  7. Rinse wash repeat till all methods are found and called.

Explanation for your example

 MRO: D,B,C,A,object  
  1. super(D, self).__init__() is called. isinstance(self, D) => True
  2. Search for next method in the MRO in classes to the right of D.

    B.__init__ found and called


  1. B.__init__ calls super(B, self).__init__().

    isinstance(self, B) => False
    isinstance(self, D) => True

  2. Thus, the MRO is the same, but the search continues to the right of B i.e. C,A,object are searched one by one. The next __init__ found is called.

  3. And so on and so forth.

An explanation of super
http://www.python.org/download/releases/2.2.3/descrintro/#cooperation
Things to watch for when using super
http://fuhm.net/super-harmful/
Pythons MRO Algorithm:
http://www.python.org/download/releases/2.3/mro/
super's docs:
http://docs.python.org/library/functions.html
The bottom of this page has a nice section on super:
http://docstore.mik.ua/orelly/other/python/0596001886_pythonian-chp-5-sect-2.html

I hope this helps clear it up.


just guessing:

self in all the four methods refer to the same object, that is, of class D.so, in B.__init__(), the call to to super(B,self) knows the whole diamond ancestry of self and it has to fetch the method from 'after' B. in this case, it's the C class.