[Python-Dev] New metaclass pattern (Was Re: Simulating Class (was Re: Does Python have Class methods))

Guido van Rossum guido at digicool.com
Wed May 23 20:02:06 CEST 2001


> [this message has also been posted to comp.lang.python]
[And I'm cc'ing there]

> Guido's metaclass hook in Python goes this way:
> 
> If a base class (let's better call it a 'base object')
> has a __class__ attribute, this is called to create the
> new class.
> 
> >From demo/metaclasses/index.html:
> 
> class C(B):
>     a = 1
>     b = 2
> 
> Assuming B has a __class__ attribute, this translates into:
> 
> C = B.__class__('C', (B,), {'a': 1, 'b': 2})

Yes.

> Usually B is an instance of a normal class.

No, B should behave like a class, which makes it an instance of a
metaclass.

> So the above code will create an instance of B,
> call B's __init__ method with 'C', (B,), and {'a': 1, 'b': 2},
> and assign the instance of B to the variable C.

No, it will not create an instance of B.  It will create an instance
of B.__class__, which is a subclass of B.  The difference between
subclassing and instantiation is confusing, but crucial, when talking
about metaclasses!  See the ASCII art in my classic post to the
types-sig:
http://mail.python.org/pipermail/types-sig/1998-November/000084.html

> I've ever since played with this metaclass hook, and
> always found the problem that B would have to completely
> simulate the normal python behaviour for classes (modifying
> of course what you want to change).
> 
> The problem is that there are a lot of successful and
> unsucessful attribute lookups, which require a lot
> of overhead when implemented in Python: So the result
> is very slow (too slow to be usable in some cases).

Yes.  You should be able to subclass an existing metaclass!
Fortunately, in the descr-branch code in CVS, this is possible.  I
haven't explored it much yet, but it should be possible to do things
like:

Integer = type(0)
Class = Integer.__class__   # same as type(Integer)

class MyClass(Class):
    ...

MyObject = MyClass("MyObject", (), {})

myInstance = MyObject()

Here MyClass declares a metaclass, and MyObject is a regular class
that uses MyClass for its metaclass.  Then, myInstance is an instance
of MyObject.

See the end of PEP 252 for info on getting the descr-branch code
(http://python.sourceforge.net/peps/pep-0252.html).

> ------
> 
> Python 2.1 allows to attach attributes to function objects,
> so a new metaclass pattern can be implemented.
> 
> The idea is to let B be a function having a __class__ attribute
> (which does _not_ have to be a class, it can again be a function).

Oh, yuck.  I suppose this is fine if you want to experiment with
metaclasses in 2.1, but please consider using the descr-branch code
instead so you can see what 2.2 will be like!

--Guido van Rossum (home page: http://www.python.org/~guido/)




More information about the Python-list mailing list