[Python-ideas] A way out of Meta-hell (was: A (meta)class algebra) (original) (raw)

Martin Teichmann lkb.teichmann at gmail.com
Tue Feb 17 11:10:00 CET 2015


Hi Petr, Hi Andrew, Hi list,

(responding to my own post, as I cannot respond to Petr's and Andrew's at the same time)

- is it desirable to have a programmatic way to combine metaclasses?

there seems to be general agreement that there should be no automatic combination of metaclasses, while many think that explicit combination should be possible.

The only way to do that currently is by subclassing existing metaclasses. This is typically done by the user of the metaclass, not its author. It would be a nice thing if an author could do that. Petr argues s/he already can, by subclassing. Unfortunately, this is not so easy as this means that every user of such a class then has to use all inherited metaclasses.

As an example: imagine you have a metaclass that mixes well with PyQt's metaclass. Then you could simply inherit from it. But this would mean that every user of you class also has to install PyQt, no matter if the code has anything to do with it.

Now Thomas argues that this should simply not be done at all. I understand his argument well that multiple inheritance across project boundaries is probably a bad idea in most cases.

But I have an example where it does make a lot of sense: ABCs. It would just be nice if one could implement and ABC which is a QObject. That's what ABCs are for. Sure, you can do this by registering the class, but this means you loose a lot like already predefined methods of an ABC. But maybe we can just special-case ABCs.

- if yes, how should that be done?

So I proposed two ways how this could be implemented: One is to change the current metaclass combination code to check whether a class is a subclass not by PyType_IsSubtype, but by PyObject_IsSubclass, meaning that the subclasshook is called. This has the advantage of being only a minimal change to the python core, I'm not sure how many people out there new at all how the subclass detection was done.

It is also very systematic: it is very analog to ABCs, just the other way around. An AbstractMetaClass would simply now which classes exist and how they can be combined. Either by inheriting from AbstractMetaClass, or by registering a foreign class.

This way has the drawback of being rather complex on the python side. But actually, I prefer complexity on the Python- over complexity on the C side.

This proposal is at https://github.com/tecki/cpython/commits/metaclass-issubclass

My other proposal was to have a way to explicitly combine (meta)classes, by having a method in the type object (I originally called that add, people didn't like that so I renamed it to merge).

This idea has somewhat more code on the C side, but is simpler on the python side. It might also be easier to grasp by newbies. Otherwise it is about as powerful as the other idea.

This proposal is at https://github.com/tecki/cpython/commits/metaclass-merge

Once we have one of my ideas implemented, I think we can implement PEP 422 in the standard library. Petr claims that this is just doing simple things with complex code. I disagree, I think that the current metaclass code in the python interpreter is already incredibly context, and just throwing more code at it is actually a very complex solution. Sure, on the python side all looks pretty, but only because we swept all complexity under the C carpet. But I won't fight for that point. What I am fighting for is to modify PEP 422 in a way that it can be backported to older versions of python and be put on PyPI. This means that init_class should become init_subclass, meaning that only subclasses are initialized. (init_class doesn't work properly, as super() won't work. This problem already exists in the zope version).

There is also a completely different way we could solve all those problems: abandon metaclasses for good, and replace them eventually with a PEP 422 like approach. This would mean that on the long run the following should be added:

A pure python version of this proposal (it would go into C, for sure) can be found here: https://github.com/tecki/metaclasses

Note that this is much more complicated as it would need to be if only the original PEP422 ideas were implemented.

This was a long post.

Enjoy.

Greetings

Martin



More information about the Python-ideas mailing list