[Python-ideas] A (meta)class algebra

Martin Teichmann lkb.teichmann at gmail.com
Fri Feb 13 05:43:47 CET 2015


Hi Thomas, Hi list,

> 1. More magic around combining metaclasses would make it harder to follow
> what's going on. Explicit (this has a metaclass which is a combination of
> two other metaclasses) is better than implicit (this has a metaclass which
> can combine itself with other metaclasses found from the MRO).

Well I disagree. If you follow this rule, everyone who uses a metaclass
needs to know how to combine it with another metaclass. This
leads to code like (I'm citing IPython.qt.console.console_widget):

class ConsoleWidget(MetaQObjectHasTraits('NewBase',
(LoggingConfigurable, QtGui.QWidget), {})):

which, in my opinion, is hard to read and grasp. Everyone has to
be taught on how to use those metaclass mixers.

> 2. I *want* it to be hard for people to write multiple-inheriting code with
> multiple metaclasses. That code is most likely going to be a nightmare for
> anyone else to understand, so I want the person creating it to stop and
> think if they can do it a different way, like using composition instead of
> inheritance.

I'm completely with you arguing that inheritance is overrated and
composition should be used more often. Yet, I actually think that
the above example is actually not such a bad idea, why should a
QWidget not be LoggingConfigurable, and have traits? Whatever
that might mean in detail, I think most programmers do get
what's going on. It's just that

class ConsoleWidget(LoggingConfigurable, QtGui.QWidget):

is much more readable. Is there magic going on in the background?
Well, to some point, yes. But it is explicit magic, the authors of
the metaclasses have to explicitly write an __add__ method to
do the metaclass combination. In this regard, it's actually more
explicit than the metaclass mixing function as above and
also mentioned by Anthony (how do I respond to two mails on a
mailing list at the same time?), which typically stuff together
metaclasses without thinking to much about them.

I also don't see how this is harder to refactor. If everyone has
to explicitly combine to metaclasses if needed, you will have
to change all that code if the details of combining the metaclasses
change. In my version, one would just have to touch the metaclass
code.

This becomes even worse if you want to add a metaclass to a class.
Then you have to change every class that inherits from it. Now you
say that code with multiple metaclasses is a bad thing in general,
but I don't agree. There are very simple examples where it makes
a lot of sense. Say, you want to write a class with traits that
implements an abstract base class. Wouldn't it be cool if you could
write

    class Spam(SpamABC, SomethingWithTraits):

instead of writing

    class Spam(SomethingWithTraits):
       ...
    SpamABC.register(Spam)

?

Greetings

Martin


More information about the Python-ideas mailing list