Multiple inheritance is GOOD
By: Kerim in python
A long, long time ago someone told me that multiple inheritence is a very bad, bad thing.
Now suppose you have a class that has a set of attributes A and you have one that has a set of attributes B. A third class has A and B, a fourth has A and D, a fifth B and D. What happens if you have some tens of classes of that sort with an amount of perhaps 20 attribute sets and all that in the wildest possible combinations. Still with me? Well such a chaos is called SVG (here is a nice example) and for quite some time i was figuring out how to best arrage the python classes in order to keep redundant repetitions out of my codebase.
I had not realized how much the mantra of decade old teachings had infiltrated my thinking until by sheer desperation i entered "python multiple inheritance" into that "fraggin" google search box. And i learned that python does support multiple inheritance. With all the previous experiences concerning svg coding i thought i couldnt loose much trying it out and it turned out to be far better than i had feared (or "learned") before.
Problems with multiple ineritance could be that you end up not knowing where a variable actually comes from if two or more of the classes that you extend happen to have the same members. Another fear I had was that perhaps the IDE would run into trouble with its autocomplete fucntions (you know ... the nice things that make lazy programmers happy).
But after just reprogramming 80% of my svg library in one day, i think i can say that multiple inheritance is NOT "per se" bad. PyDev (which i use for programming) seems to get along rather well still with the classes. And when it comes to the question where which variable comes from Python helps you a bit though by simply taking the variable from the class that is defined first.
So a:
class myclass(A,B,C)....
where A and B and C define lets say a member "X" method, would result in the X of class A to be taken for myclass. A clear and good solution. I am not sure yet how documentation tools handle this, nor do i know if the mere fact that python takes the first definition of a variable or method really helps someone trying to understand the code (after all he doesnt know where the variable is initially placed). But given my experience with the initial problem i find this an interesting path to follow for a while.
:-) Man i must really have been frustrated to post about such a trivial discovery :-)
PS: pySVG +=0.1 is not far away. My worst problem at the moment is a naming conflict with some other guy who has the same name for his lib and not written anything for it for 4 years.




on 23 September 2009 at 11:01 Rene Dudfield said …
Hi,
what about pyglet.svg svgpy svpyg svgraphics syg?
yeah, it's all that java propaganda that's seeped into our heads, and bad C++ experiences people have had... plus some bad python experiences rolled in :)
The good thing about it... is it's easy(to start with)!
The main problems with Multiple Inheritance(MI) are readability and extensibility down the road. It makes reasoning about the Method Resolution Order MRO a bit more difficult(searching for methods etc). But I think this depends on the code, and the docs!
Composition with interfaces is the main alternative in python. It's main benefit is that you can compose classes more easily, and be a bit more explicit about what is happening. Composition also lets you change things a bit more easily later(extensibility).
ABCs are the new hotness in the python3 world... and zope.interface is pretty popular for interfaces too.
But I agree, MI can be quite easy to use initially... but I steer clear of it because things can go wrong with it more easily in large cases.
I think MI can be a bit more useful with unittests... since you can run all the tests for the various classes and see if they work. 'cause how do you know if you combine two classes that they'll pass the tests for all the parents? With skipping tests, and specific tests for the children it could work. You'd need to use factories for your tests though. I haven't really tested a big MI code base... but it's interesting to consider how you'd do it.
For some problems MI just seems to work better... but maybe not for every thing. The SVG was designed with MI so MI is a great fit to implement it. Some people have implemented it with interfaces too.
"In Mozilla's SVG implementation we have implemented the SVG DOM by keeping one single principal inheritance thread for the interfaces & 'promising' to implement all the other interfaces that would otherwise be mixed into the interface tree. E.g. we inherit the SVGCircleElement interface directly from SVGElement (which in turn inherits from Element and Node) and 'promise' that every object implementing SVGCircleElement also implements the interfaces SVGStylable, SVGTransformable etc. "
cu,
on 23 September 2009 at 11:57 James Thiele said …
One reason you may have been told that multiple inheritance is bad is that in C++ the rules for multiple inheritance are in some cases almost incomprehensible, as a C++ instructor once admitted to me. In Python while not always simple multiple inheritance rules work nicely.
on 23 September 2009 at 18:24 Rui Ferreira said …
At least it's better than mixins!
on 24 September 2009 at 02:02 Kerim Mansour said …
"The main problems with Multiple Inheritance(MI) are readability and extensibility down the road. It makes reasoning about the Method Resolution Order MRO a bit more difficult(searching for methods etc). But I think this depends on the code, and the docs!"
I thought so too. SVG seems to be a case where this problem doesn't arise so fast I think. The specification of it is easily visible even if the code documentation would be lacking.
And the amount of classes is (in my current view) relatively low compared to "larger" projects.
As for the interfaces, that is something rather new to me. Coming from the Java-world i learned pretty soon that there seems to be no comparable to a Java Interface in the python world. And i also see no reason why there should be given that Python uses duck typing.
Apart of that i do not think it helps much in this special case as interfaces only define method "stubs"(at least in Java). The actual implementation would have to be done in the implementing classes which would result in very much code looking all the same. After all we only speak (in pySVG) about getters and setters that set a value in a dictionary.