circular dependency between class and its metaclass

Jp Calderone exarkun at intarweb.us
Sun Jan 18 14:58:49 EST 2004


On Sun, Jan 18, 2004 at 03:03:48PM -0500, Stefan Seefeld wrote:
> hi there,
> 
> I'v run into a little problem for which I only found an ugly workaround,
> so I'd like to know whether people are aware of better ways to achieve 
> this...
> 
> I'm defining a class 'Class' for which I want to set up a __metaclass__ 
> 'Type'
> which does some work on class variables. In particular, it should apply
> a function on all base classes that are themself derived from 'Class'.
> 
> My first try was:
> 
> ====
> 
> class Class(object):
> 
>     class Type(type):
> 
>         def __init__(cls, name, bases, dict):
> 
>             hierarchy = list(filter(lambda i:issubclass(i, Class), bases))

    hierarchy = [i for i in bases if isinstance(i, Type)]

>             # do something with the hierarchy here
> 
>     __metaclass__ = Type
> 
> ====
> 
> However, this fails because at the point where I want to create the
> 'hierarchy' variable 'Class' isn't known yet. (At what point is it actually
> injected into the local dict ?)
> 

  It is added after the class object is created, which is more or less after
the dedent token at the end of the class definition.  So, for:

    class Foo:          # A
        pass            # B
    x = Foo()           # C

  `Foo' is bound between lines B and C.


> Then I tried to define 'Type' after 'Class' (instead of inside it):
> 
> ====
> 
> class Class(object): pass #supress details for clarity
> 
> class Type(type):
>     ...
> 
> Class.__metaclass__ = Type
> 
> ====
> 
> But this didn't work at all (even though I don't quite understand why).

  The __metaclass__ variable must be set before the class is defined,
because it is used to determine how the class object will actually be
created.  Once the class object has already been created, the __metaclass__
variable is meaningless.

> [snip last case - workaround]

  Jp




More information about the Python-list mailing list