Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is super used so much in PySide/PyQt?

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

like image 217
eric Avatar asked Jun 01 '14 15:06

eric


People also ask

Is PySide better than PyQt?

PySide is LGPL while PyQt is GPL. This could make a difference if you don't wish to make your project opensource. Although PyQt always has the propriety version available for a fairly reasonable price. I tend to find the PySide documentation more intuitive.

Why use PySide instead of PyQt?

Advantages of PySide PySide represents the official set of Python bindings backed up by the Qt Company. PySide comes with a license under the LGPL, meaning it is simpler to incorporate into commercial projects when compared with PyQt. It allows the programmer to use QtQuick or QML to establish the user interface.

Is PySide and PyQt the same?

The short answer is that the reason lies mainly in license related issues and that PyQt and PySide are actually very similar, so similar that the code below for a QT based version of the miles-to-kilometers converter works with both PyQt and PySide. For PySide you only have to replace the import line at the beginning.

Does PyQt cost money?

PyQt is free software developed by the British firm Riverbank Computing. It is available under similar terms to Qt versions older than 4.5; this means a variety of licenses including GNU General Public License (GPL) and commercial license, but not the GNU Lesser General Public License (LGPL).


2 Answers

There is nothing wrong with instantiating parent classes in the traditional way, and some things to be said in favor of it. That said, using super simplifies the creation of subclasses, and the future modifications of one's PySide code, and people seem to have latched onto the latter as the overriding factor. This is not specific to Pyside, but to object-oriented programming in Python more generally (as pointed out in Kos's excellent answer).

The potential for simplification of code modification comes because within PySide it is necessary for things to work to define subclasses based on other QtGui objects (e.g., QtQui.QMainWindow and QtGui.QWidget). Further, people tend to futz around with their parent classes enough so that it seems easier to just use super, so that you you don't have to update your __init__ method every time you change parents.

So it isn't a matter of using super to help resolve cases of multiple inheritance, the case where most people agree it is probably best suited. Rather, it is a matter of doing less work within __init__ in case your parent class changes in the future.

Here are the responses from each author, both of whom wrote what I consider to be good PySide tutorials:

Author 1:

I think it is a matter of taste. Earlier tutorials (PyQt and PySide) used .init and later I switched to super(). I personally prefer super().

Author 2:

The reason people use super instead of .init(...) is to avoid making changes if you change what the parent class is, e.g. if you switch from QVBoxLayout to QHBoxLayout, you only have to change it in the class definition line, rather than in the init method as well.

So there you have it. Not these benefits aren't really specific to PySide, but to writing subclasses/inheritance more generally.

I'm not sure what Lutz, who seems very hesitant to endorse the use of super, would say (perhaps using super violates the 'Explicit is better than implicit' maxim).

Update Four Years Later
In retrospect, this debate is sort of over and this question is almost quaint (this was my first question at SO). While there used to be debate about the use of super, these debates are sort of over. Especially in Python 3 super's convenience has proven itself and just makes your code easier to maintain. Because in Qt/Pyside/PyQt framework the use of inheritance from more abstract Qt classes is ubiquitous, this is no small feature. Sure, you will need to be careful when you have crazy lattices of inheritance, but frankly since I asked this question, I have literally never run into this problem, and I currently use super in all my code. It arguably violates the "explicit is better than implicit" maxim, but "Simple is better than complex" and "practicality beats purity" are the overriding factors here (the practical aspect here is "maintainability counts").

like image 164
eric Avatar answered Oct 10 '22 04:10

eric


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:

  • Method resolution order - what's it all about
  • Python's Super is nifty, but you can't use it

[

like image 35
Kos Avatar answered Oct 10 '22 02:10

Kos