circular dependency between class and its metaclass

S

Stefan Seefeld

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))
# 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 ?)

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).

Then I tried a workaround using an auxiliary base class:

====

class Base(object): pass #supress details for clarity

class Type(type):
def __init__(cls, name, bases, dict):

# now base the filter on 'Base'
hierarchy = list(filter(lambda i:issubclass(i, Base), bases))
# do something with the hierarchy here

class Class(Base):

__metaclass__ = Type

...

====

though this is quite ugly, as 'Class' is the class that provides the stuff
the 'Type' constructor should act on, not 'Base' (so to make the filter above
work I have to do some more ugly tricks).

I'd very much appreciate if anybody could shed some light on why python
behaves the way it does in the two first cases, and whether there are
better ways to achieve what I want. Thanks a lot !

Stefan
 
M

Michele Simionato

Stefan Seefeld said:
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))
# do something with the hierarchy here

__metaclass__ = Type

If "i" is a subclass of Class, then it is an instance of Type: this means
that you can write

class Type(type):
def __init__(cls, name, bases, dict):
hierarchy = [i for i in bases if isinstance(i, Type)]
# I like list comprehension...

class Class(object):
__metaclass__ = Type

Is this nice enough for you?

Michele Simionato
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top