[Types-sig] Re: Meta-classes discussion starter

Just van Rossum just@letterror.com
Mon, 30 Nov 1998 23:08:16 +0100


At 2:05 PM -0600 11/30/98, Evan Simpson wrote:
>Perhaps I'm thinking too statically, but to my mind, you don't specify the
>metaclass of a class any more than you specify the class of an instance (by
>"calling" the (meta-)class).  This is essentially where my two meta-class
>problems arise.

Hmmm...

- when you call a class it returns a new instance
- when you call a metaclass it returns a new class

That could make for some interesting Python 2.0 syntax:
	class MyClass = MyMetaClass(BaseClass1, ..., BaseClassN): ...etc.
where
	class MyClass(BaseClass1, ..., BaseClassN): ...
would be a shortcut for
	class MyClass = ClassClass(BaseClass1, ..., BaseClassN): ...etc.
(where ClassClass is the default metaclass)

(Sorry, I didn't read the egroups archive so I have not seen David's syntax
proposal.)

Not sure whether I like that...


On a related note, while studying Guido's MetaClass essay and the
accompanying code (initially my head exploded every five minutes, today I
got by with only once) an idea for Yet Another MetaHook occurred to me.
After I sortof understood Guido's stuff I became annoyed by the fact that
the inheritance syntax gets abused to specify a metaclass. Which has as a
side effect that you _have_ to make an instance of the metaclass to be able
to use it as a metaclass, and that you _have_ to use the original class for
real subclassing. (And in turn you have to instantiate that subclass to use
it.) Two objects to refer to the same concept: very confusing (at least for
me ;-). While digging in ceval.c and understanding how the Don Beaudry and
Guido's own hook actually work I came up with mine, which I define thusly:

	If the __dict__ of the class that is being built has a __class__
	key, call that thing with (name, bases, methods)

Which means you specify a metaclass like this:

class MyClass:
	__class__ = MyMetaClass

Not exactly pretty, but at least it doesn't look like inheritance. It also
means that if you want to subclass from MyMetaClass you write

class MyOtherMetaClass(MyMetaClass): ...

With Guido's hook the above looks like this:

MyMeta = MyMetaClass("MyMeta", (), {})

class MyClass(MyMeta): ...

class MyOtherMetaClass(MyMetaClass): ...

MyOtherMeta = MyOtherMetaClass("MyOtherMeta", (), {})


The cool thing is that inheritance from a class that has a meta class works
like you would expect, because of Guido's hook...


This is not theory: I've got it working right here, and I seriously propose
it for 1.6, if not 1.5.2. (If anyone wants to play, I could post a patch.)


Then...
...I tried to emulate the Python class/instance model using metaclasses,
but I got stuck several times due to severe brain damage alternated with
head explosion. But I believe now that that's not the fault of metaclasses
in Python, but that it is just really hard to do, largely because of
problems Evan noticed, too. Simple example, if you do
	repr(object)
the current Python semantics say: get the __repr__ attribute of object.
Which means if object is an instance, first it's __dict__ will be searched,
then its __class__ and then it's base classes. Usually, object.__repr__ is
the same as object.__class__.__repr__. Now what if you want to repr() the
class? The easiest thing I could think of to define __repr__ (and some
others, like __call__) as special, and _never_ search the object itself,
but only its class. So object.__repr__ lives in object.__class__ and
object.__class__.__repr__ lives in object.__class__.__class__.__repr__.
Phew.

Anyway, thanks for listening...

Just