[PyQt] Fwd: Fwd: Mixin classes and PyQt4

Martin Teichmann martin.teichmann at gmail.com
Wed Feb 12 08:57:04 GMT 2014


Hi Baz,

> On the face of it, in your example, how is it possible for B to have
access to a depth() method
> when it is not defined in the body of the class?  This method is actually
provided by a Qt mixin
> (QPaintDevice), but this is obscured by the syntax of vertical
inheritance. You are viewing the
> hierarchy from the top down, so all the layers just merge into one
another.

Well, the big difference is, QWidget inherits from QPaintDevice, from which
B inherits. For sure,
B can access depth(). In order to get a similar example, it would be
necessary for QPaintDevice
to access methods of QWidget - which it cannot, except QWidget overwrites
methods which
QPaintDevice already has. In your version of my example, B does not inherit
from QObject,
but still calls its methods. That's what I call weird.

Sure, you could argue that this is just a limitation of C++ which Python
simply does not have.
The way that virtual methods are implemented in C++ makes such flexibility
impossible.
On the other hand, in python, even monkey-patching is allowed, but I guess
you would
agree that this is bad style only to be used if there is really no other
way.

> A mixin is part of a deconstructed subclass. The layer containing the
additional and reimplemented
> members of the subclass (which would normally be defined in its body) is
detached from the top of
> the vertical hierarchy and arranged horizontally instead. And in the
horizontal dimension of inheritance,
>  classes are ordered left to right - so naturally the A mixin of your
example must go to the left of the
> QLabel base-class. It can never make any sense for it to go on the right
(that would be like saying
> B somehow belongs at the bottom of the vertical hierarchy).

Nevertheless, even in those horizontal schemes all classes in the end
inherit from object. Indeed, they
should inherit from all classes whose methods they are using (in their
original or overwitten form) just
to assure that they exist at all. Putting QObject into my inheritance list
of the Mixin class means
nothing more than "hey python, I need the methods of QObject, so please put
me before it in the MRO".

Without using the notion of mixin classes at all, one can even generalize
this. In a cooperative
inheritance scheme, for each method that takes part in this scheme, there
must be one end-of-chain
method, which does not call super(). If it would, one would just get an
error saying the
method does not exist in the super class. (In the case of __init__, object
is such a end-of-chain, as it
does not call super as it knows that there is no super). Now all classes
that are cooperating better
inherit from this end-of-chain class in order to be put before this class
in the MRO, otherwise they
might not be called. PyQt, not calling any super() (except sometimes for
__init__) is always such
an end-of-chain. So its classes should be listed in each mixin class that
uses methods from a PyQt
class.

Btw, given that you have cooperating classes (I do not argue that PyQt
should in any way be cooperative
or not, I'm now talking in general terms) it could actually well make sense
for a mixin class to go to the
right - if it should be called after the specialized class. My example was:

class A(QObject):
    pass

class B(QWidget, A):
    pass

in which case the MRO is B, QWidget, A, QObject. Again, this won't ever
work with PyQt, so actually
PyQt should prevent you from doing so (my code patch could be extended in
such a way).

So in general, it is a good idea to list the classes that you're using even
in mixin classes. This is
good practice in python, and so it should be in PyQt. Unfortunately, this
good practice is impossible
in PyQt. This is the detail my patch adresses. This is what I call cool and
nice.

Greetings

Martin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20140212/4ab7a9a1/attachment.html>


More information about the PyQt mailing list