<div dir="ltr">Hi Baz,<br><div class="gmail_quote"><div class=""><br>> On the face of it, in your example, how is it possible for B to have access to a depth() method <br>> when it is not defined in the body of the class? This method is actually provided by a Qt mixin <br>
> (QPaintDevice), but this is obscured by the syntax of vertical inheritance. You are viewing the<br>> hierarchy from the top down, so all the layers just merge into one another.<br><br></div><div class="">Well, the big difference is, QWidget inherits from QPaintDevice, from which B inherits. For sure,<br>
</div><div class="">B can access depth(). In order to get a similar example, it would be necessary for QPaintDevice<br></div><div class="">to access methods of QWidget - which it cannot, except QWidget overwrites methods which<br>
QPaintDevice already has. In your version of my example, B does not inherit from QObject,<br>but still calls its methods. That's what I call weird.<br><br></div><div class="">Sure, you could argue that this is just a limitation of C++ which Python simply does not have.<br>
The way that virtual methods are implemented in C++ makes such flexibility impossible. <br>On the other hand, in python, even monkey-patching is allowed, but I guess you would<br></div><div class="">agree that this is bad style only to be used if there is really no other way.<br>
</div></div><div class="gmail_quote"><br>> A mixin is part of a deconstructed subclass. The layer containing the additional and reimplemented <br>> members of the subclass (which would normally be defined in its body) is detached from the top of<br>
> the vertical hierarchy and arranged horizontally instead. And in the horizontal dimension of inheritance,<br>> classes are ordered left to right - so naturally the A mixin of your example must go to the left of the <br>
> QLabel base-class. It can never make any sense for it to go on the right (that would be like saying <br>> B somehow belongs at the bottom of the vertical hierarchy).<br><br></div><div class="gmail_quote">Nevertheless, even in those horizontal schemes all classes in the end inherit from object. Indeed, they<br>
</div><div class="gmail_quote">should inherit from all classes whose methods they are using (in their original or overwitten form) just<br></div><div class="gmail_quote">to assure that they exist at all. Putting QObject into my inheritance list of the Mixin class means <br>
nothing more than "hey python, I need the methods of QObject, so please put me before it in the MRO".<br><br></div><div class="gmail_quote">Without using the notion of mixin classes at all, one can even generalize this. In a cooperative<br>
</div><div class="gmail_quote">inheritance scheme, for each method that takes part in this scheme, there must be one end-of-chain<br>method, which does not call super(). If it would, one would just get an error saying the <br>
</div><div class="gmail_quote">method does not exist in the super class. (In the case of __init__, object is such a end-of-chain, as it<br>does not call super as it knows that there is no super). Now all classes that are cooperating better<br>
inherit from this end-of-chain class in order to be put before this class in the MRO, otherwise they<br></div><div class="gmail_quote">might not be called. PyQt, not calling any super() (except sometimes for __init__) is always such<br>
an end-of-chain. So its classes should be listed in each mixin class that uses methods from a PyQt<br>class.<br></div><div class="gmail_quote"><br></div><div class="gmail_quote">Btw, given that you have cooperating classes (I do not argue that PyQt should in any way be cooperative<br>
or not, I'm now talking in general terms) it could actually well make sense for a mixin class to go to the<br></div><div class="gmail_quote">right - if it should be called after the specialized class. My example was:<br>
<br></div><div class="gmail_quote">class A(QObject):<br></div><div class="gmail_quote"> pass<br><br>class B(QWidget, A):<br></div><div class="gmail_quote"> pass<br><br>in which case the MRO is B, QWidget, A, QObject. Again, this won't ever work with PyQt, so actually<br>
</div><div class="gmail_quote">PyQt should prevent you from doing so (my code patch could be extended in such a way).<br><br>So in general, it is a good idea to list the classes that you're using even in mixin classes. This is<br>
</div><div class="gmail_quote">good practice in python, and so it should be in PyQt. Unfortunately, this good practice is impossible<br>in PyQt. This is the detail my patch adresses. This is what I call cool and nice.<br>
</div><div class="gmail_quote"><br>
</div>Greetings<br><br>Martin<br></div>