Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PyQt4: why do we need to pass class name in call to super()

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__()
like image 746
rock Avatar asked Mar 30 '14 12:03

rock


1 Answers

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.

like image 136
Bakuriu Avatar answered Sep 17 '22 23:09

Bakuriu