Why is super used so much in PySide/PyQt?

eric picture eric · Jun 1, 2014 · Viewed 10.6k times · Source

Short version (tl;dr)

I am learning PySide, and most online tutorials use super to initialize UI elements. Is this important (i.e., more scalable), or is it a matter of taste?

Clarification: as I make more clear in the detailed version, this is not another generic thread asking when to use super (this has been done before). Rather, given the number of PySide tutorials that use super instead of <class>.__init__, I am trying to figure out if using super is standard in PySide applications? If so, is it because the circumstances where super is called for (involving resolving inheritances) come up a lot specifically in the use of PySide/PyQt? Or is it a matter of taste.

Detailed version

I am new to Python, and presently learning PySide using Zets tutorial (http://zetcode.com/gui/pysidetutorial/firstprograms/). The second example in the tutorial includes:

from PySide import QtGui

class Example(QtGui.QWidget):
    def __init__(self):      
        super(Example, self).__init__()
        self.initUI()
    def initUI(self):
        self.setGeometry(300,300,250,150)
        self.setWindowTitle("PySide 101: Window the First!")
        self.show()

app=QtGui.QApplication(sys.argv)
ex=Example()
sys.exit(app.exec_())    

This works fine, but I have never used super. Hence, I rewrote the above code, successfully replacing super with more standard explicit invocation of the parent class:

QtGui.QWidget.__init__(self)

But as I search the web for PySide tutorials (e.g., http://qt-project.org/wiki/PySide-Newbie-Tutorials), they all include calls to super. My question is: should I use super for PySide scripting?

It seems that super seems most helpful when you have inheritance diamonds, that it tends to resolve instances of multiple inheritance in a reasonable way. Is super used a lot with PySide because there is a preponderance of cases of such diamonds that I will confront with more realistic complicated examples? [Edit: No: see my answer below.]

Why am I even asking? Why not just use super and be done with it?

I am asking because the book I am using to learn Python (Learning Python, by Lutz) spends over 20 pages on the topic of super, and explicitly cautions against using it. He suggests that new Python users go with the more traditional, explicit route before messing with it (e.g., see page 832, and pages 1041-1064 of Learning Python, 5th Edition). He basically paints it as a nonPythonic, arcane, rarely actually needed, new style that you should treat with great caution when just starting out, and thinks it is overused by experienced users.

Further, looking at the source code of two major PySide/PyQt based projects (Spyder and pyqtgraph), neither uses super. One (Spyder) explicitly tells contributors to avoid using it for compatibility reasons (http://code.google.com/p/spyderlib/wiki/NoteForContributors).

Note I link to a closely related post below, but the answer there discusses more generally when you would want to use super (when you have multiple inheritance). My question is whether PySide scripting justifies, or even requires, the use of super in the long term, or whether it is more Pythonic, and better for compatibility reasons, to explicitly name parent classes? Or is it a matter of taste?

If it is frowned upon (as my beginner book suggests) why is it so ubiquitous in PySide tutorials aimed at beginners? If it makes any difference, it seems the people writing these tutorials are seasoned Java programmers, or catering to such programmers. I am not.

Related topics

http://www.riverbankcomputing.com/pipermail/pyqt/2008-January/018320.html

Different ways of using __init__ for PyQt4

Understanding Python super() with __init__() methods

Answer

Kos picture Kos · Jun 1, 2014

Hm, nice one. But IMO it's only barely related to Qt/ PySide.

First, how are these two different? If you have simple inheritance (perhaps not counting "mixins"), then there's no difference in behaviour. A cosmetic difference remains- you don't need to name your base class again - but you do have to name the same class.

The differences start when you have multiple inheritance. Then a chain of super() calls for this hierarchy:

          A
        /   \
       X     Y
        \   /
          Z

can easily proceed like this through super() calls:

          A
            \
       X --- Y
        \   
          Z

without the need of X and Y knowing each other. This relates to the concept of method resolution order that allows a style of programming called "cooperative multiple inheritance" in the Python docs.

If there's a method Foo and implementations in X and Y of that method build upon A's implementation, then Z is easily able to rely on both X and Y without them knowing even about each other. This, however, has an important precondition: Foo has the same (or at least [compatible]) signature in every class, as specified by A's interface where it's initially defined.

The __init__ method is special: technically it works in exactly the same way with super, but! but (more often than not) for subclasses it has a totally different signature. If the subclass' __init__ looks different, then super won't give you anything over explicit base call because you aren't able to use cooperative multitasking anyway.

Note: Python is very atypical in this respect: in most OO languages constructors belong to the class, rather than the instances; in other words most languages rely on their equivalents of __new__ and don't have __init__ at all.

Note 2: I have never seen any real code that would rely of cooperative multiple inheritance. (Single inheritance easily makes enough spaghetti for me ;-))

Also, some good reading:

[