Question

as in the following code super(MdiChild, self).__init__() we are passing mdichild in the super function.please explain me why and why .__init__() is used.

class MdiChild(QtGui.QTextEdit):
   sequenceNumber = 1

   def __init__(self):
      super(MdiChild, self).__init__()
Was it helpful?

Solution

In python3.3+ you don't need to pass the class name explicitly, you can just do:

super().__init__()

Now, note that super does not call the constructor. It simply provides an object where you can access the attributes of the given instance as if it was an instance of the parent class. For example you could call setText:

super().setText('Hello')  # calls QLineEdit.setText

In python<3.3 super is a normal function. It doesn't have anything special. This means that it does not know from which class it was called, and hence it cannot now how to find the parent class without passing the arguments explicitly. Also you may want to do things like:

super(QLineEdit, self).__init__()

Which would call QLineEdit's parent class __init__() (i.e. the grand-parent __init__() function).

From python3.3 a "hack" was added so that the call to super without arguments is equivalent to calling super(CurrentClass, self). This required some changes in the compiler.


Here's a simple example of how super works:

In [1]: class MyBase(object):
   ...:     def __init__(self):
   ...:         print('MyBase.__init__() called')

In [2]: class MyChild(MyBase):
   ...:     def __init__(self):
   ...:         print('MyChild.__init__() called')
   ...:         super().__init__() # MyBase.__init__
   ...:         

In [3]: class MyGrandChild(MyChild):
   ...:     def __init__(self):
   ...:         print('MyGrandChild.__init__() called')
   ...:         super().__init__()  # MyChild.__init__
   ...:         print('Between super calls')
   ...:         super(MyChild, self).__init__()  # MyBase.__init__
   ...:         super(MyBase, self).__init__() # object.__init__ (does nothing)

In [4]: MyGrandChild()
MyGrandChild.__init__() called
MyChild.__init__() called
MyBase.__init__() called
Between super calls
MyBase.__init__() called

In python<3.3 where you cannot omit the class name every call to super() without arguments must be replaced with:

super(NameOfCurrentClass, self)

For example:

In [7]: class MyBase(object):
   ...:     def __init__(self):
   ...:         print('MyBase.__init__() called')

In [8]: class MyChild(MyBase):
   ...:     def __init__(self):
   ...:         print('MyChild.__init__() called')
   ...:         super(MyChild, self).__init__()

In [9]: class MyGrandChild(MyChild):
   ...:     def __init__(self):
   ...:         print('MyGrandChild.__init__() called')
   ...:         super(MyGrandChild, self).__init__()
   ...:         print('Between super calls')
   ...:         super(MyChild, self).__init__()
   ...:         super(MyBase, self).__init__()

In [10]: MyGrandChild()
MyGrandChild.__init__() called
MyChild.__init__() called
MyBase.__init__() called
Between super calls
MyBase.__init__() called

The expression super(A, instance) means: take a proxy to object instance where I can access the methods of A's parent. The "parent" is defined by the MRO:

In [12]: MyGrandChild.__mro__
Out[12]: (__main__.MyGrandChild, __main__.MyChild, __main__.MyBase, builtins.object)

In the case of single inheritance is simply the name of class in the hierarchy up to object, but with multiple inheritance the tree is linearized so if class A so which method is called becomes more complicated to guess.

OTHER TIPS

Consider C inherits from B and B inherits from A and you create an object foo of type C.

foo.__init__() is C.__init__(), which calls B.__init__. But, as the object is of type C, if B.__init__ did not specify it wants to call B's parent __init__ (ie. A.__init__), it would be calling itself (ie. B.__init__), as B is the parent class of the object.

Not sure if I am clear here, I hope that helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top