AFAIK, the best use case for multiple inheritance is the plugin pattern, when you plug in methods in a class according to a given condition.
For instance: if plugin == "PDF": class DocumentGenerator(BaseGenerator, PDFMixin): pass elif plugin == "PS": class DocumentGenerator(BaseGenerator, PSMixin): pass elif plugin == "HTML": class DocumentGenerator(BaseGenerator, HTMLMixin): pass etc. This is not a bad use case (actually it is good) still I would say it is not compelling. I could just add the right methods by hand: if plugin == "PDF": DocumentGenerator = type("DocumentGenerator", (BaseGenerator,), PDFmethods) elif plugin == "PS": DocumentGenerator = type("DocumentGenerator", (BaseGenerator,), PSmethods) elif plugin == "HTML": DocumentGenerator = type("DocumentGenerator", (BaseGenerator,), HTMLmethods) or use a different design based on composition + delegation. The problem with MI is that it does not really give anything new that you cannot do in other ways (at least in a dynamic language such as Python); OTOH, it is extremely easily abused and makes difficult to reason about code. Look to what happened to Zope 2! Adding methods by hand is ugly, people would think twice before doing that; OTOH, using mixin is even worse, still it looks cool and people do not realize how bad it is. Here I speak for personal experience, as you may imagine, having both read and written MI hierarchies that could have much better written without MI. Finally, let me say that cooperative methods are terrible for maintenance. Nowadays, I tend to use MI just for debugging (yes, a mixing is convenient, if not compelling, for adding debugging functionality to a class). Michele Simionato -- http://mail.python.org/mailman/listinfo/python-list