Discerning use of multiple inheritance is very Pythonic. Look no further than Exception use cases:

class PathAccessError(KeyError, IndexError, TypeError):

It might look a little wonky at first, but when you understand the use case, you'll see the utility. There are loads of these sorts of use cases sprinkled throughout the community, in some of the most Pythonic libraries around.

Mahmoud

On Fri, Mar 18, 2016 at 11:11 AM, Martin Teichmann <lkb.teichmann@gmail.com> wrote:
Hi List,


Summary: Multiple inheritance is not used in new code of the standard
library anymore, even where it could be of good use. Should multiple
inheritance thus be abandoned, or supported more?


I am currently developing a little library for the communication in our
project. It is supposed to support different protocols, encryptions and
addressing standards.

At first I thought I'd just use multiple inheritance. A user of the library
would then just write a little stub-class, as in:

    class MyProtocol(URLAdressMixin, SSLEncryptionMixin, HTTPProtocol):
        pass

and voilà! everything is ready.

But because I try to be one of the cool guys, I tried to do all of that using
asyncio. It has a pluggable event loop, where you can plug in your own
event loop with the specifics of your project. Again, I thought, let's
to multiple
inheritance! I needed some priority scheduling, so just write a mixin that does
that, and mix it into the base class of the event loop.

To my astonishment, the designers of asyncio explicitly decided against that
option. They prefer not to let users subclass at all. Instead, asyncio has
a factory plugin system, as an example, one can call set_task_factory
to modify what the BaseEventLoop.create_task method is doing. Things
like that used to be clearly the domain of mixin classes.

The question arised, why would one do that? Is multiple inheritance bad,
or not Pythonic?

Guessing what the decisions of the asyncio developers were, several problems
come to my mind. Firstly, metaclasses a notoriously problematic in a multiple
inheritance context. Some of you might have seen my work on PEP 487 to
mitigate that problem.

Another issue are the stub classes mentioned above.
One ends up writing lots of little stub classes combining mixins
together. (An example from
https://github.com/jupyter/qtconsole/blob/master/qtconsole/inprocess.py:
class QtInProcessKernelManager(QtKernelManagerMixin, InProcessKernelManager):)
Many users don't like that, it's too much programming, too little using.

Another problem is that mixins cannot be mixed-in at runtime anymore.
Once the event loop is running, I cannot sneak in a new task factory anymore.
It is questionable whether that's desired. Another argument is that
using the factory way, a library might "sneak in" its factories without the
user noticing. But in my opinion, that's against the Pythonic concept of
being explicit. A library should rather document: "Hey, you need to include
SuperTaskMixin into your Eventloop", rather than silently setting a new
factory.

This also touches mainainability a lot. Imagine you are using two libraries,
both at some time deciding they need to set a task factory. That won't work
out.

All of this is nicely solved in a multiple inheritance scheme: the
method resolution
order using super() is flexible enough to allow two independent extensions of
create_task, as long as it is properly documented how to use it.

So both concepts, multiple inheritance as well as pluggable factories, have
their pros and cons. According to the Zen, there should ideally only be
one way of doing things, but given that I'm not Dutch I just don't see what
that way is. Please help me out.

In my opinion, either

a) multiple inheritance should be declared not Pythonic and frowned upon, or
b) made easy to use and well supported

In case of a), it would be nice to have proper facilities set up to have a good
factory plugin mechanism (for example one that also allows to put in
several plugins)

Or in the b) case, it should be easier to use multiple inheritance and
mixins. I was thinking about a class algebra, so following the above
example one could create a mixed class simply as
MyProtocol = SSLMixin + HTTPProtocol. This would lead do options
(going back to asyncio) like

asyncio.set_event_loop((PriorityMixin + QtEventLoop)())

What do you all think about that?

Greetings

Martin
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/