[Python-ideas] A (meta)class algebra

Martin Teichmann lkb.teichmann at gmail.com
Thu Feb 12 14:42:01 CET 2015


Hi everyone,

I guess I need to give an example to show what my proposal is about.
Imagine a metaclass which registers all classes based on it:

class MetaRegistrar(type):
    def __init__(self, name, bases, dict):
        super().__init__(name, bases, dict)
        Registrar.classlist.append(self)

class Registrar(object, metaclass=MetaRegistrar):
    classlist = []

now every subclass of Registrar is registered into its classlist. Imagine
now you want to register a class which inherits another metaclass.
A real world example I stumbled over was using a QObject from PyQt4.
Then you have:

class Spam(Registrar, QObject):
    pass

which gives you a nice error message. Sure, you can now define a new
metaclass:

class MetaQRegistrar(MetaRegistrar, type(QObject)):
    pass

but then you always have to write something like

class Spam(Registrar, QObject, metaclass=MetaQRegistrar):
    pass

everyone who uses Registrar needs to know the details of how those classes
can be combined. With my addition, one could simply add a method
to MetaRegistrar:

def __add__(self, other):
    class Combination(self, other):
        pass
    return Combination

which mixes MetaRegistrar into whatever comes. Sure, this is a very
simplified example, one would cache the created classes, and maybe
one wants to register classes that can be mixed.

So, I hope this helps to illustrate my idea, now I'm answering specific
questions raised:

> Why the + operator? This doesn't seem to have anything to do with
> addition, or concatentation.

well, technically I'm fine with any method name, one of the binary
operators just has the advantage that all the details with when
__add__ as opposed to __radd__ is called are all sorted out already.
But maybe the | operator is a better choice, as mixing classes is more
like a union of two sets.

> Your default implementation of __add__
> shows that this has nothing to do with anything remotely like the
> standard use of plus:

That's actually not true. My methods combine classes, and if one is
already a subclass of the other, they are already mixed, so yes,
it is like a standard union of sets (I start to like the idea of |)

> Just overriding __add__ (or whatever method used) doesn't solve the
> problem. You still have to actually make the metaclasses compatible, so
> that it is meaningful to mix the metaclasses.

Well, it does solve the problem. Before it was not at all possible to
programmatically make metaclasses compatible, you had to write it
down explicitly, each time of use.

>> They can be easily overwritten to get a different metaclass mixing
>> behavior.
>
> I question how easy that would be. If I have understood your proposal
> for metaclass __add__, mc1 + mc2 would have to return a new metaclass,
> mc3, which somehow combines behaviour from the two arguments. Even with
> cooperative metaclasses designed to work together, that sounds to me
> like it would be painful.

well, to give an example:

class MetaClassMixin(type):
    def __add__(self, other):
        class ret(self, other):
            pass
         return ret

just mixes your class into the other class.

Greetings

Martin


More information about the Python-ideas mailing list