Thanks for all the help guys ... in almost every way using a metaclass seems to be the right solution for what I'm trying to do here. I say almost because there is one thing that is still confusing me: what is the most elegant way to provide base-class implementations of methods that are expected to be overriden by some of the derived classes (or in the case of metaclasses, the classes that either declare __metaclass__ = Exposed or are derived from such classes).
Here's what I've just knocked out: import sys class Exposed( type ): def __init__( cls, *args, **kw ): # Track marked exposed methods cls.s_exposedMethods = [] for superclass in cls.__mro__: for name, meth in superclass.__dict__.items(): if hasattr( meth, "exposed" ): cls.s_exposedMethods.append( name ) # Add getExposedMethods method cls.getExposedMethods = lambda self: self.s_exposedMethods cls.bar = lambda self: sys.stdout.write( "bar\n" ) @staticmethod def expose( f ): f.exposed = True return f class Process( object ): __metaclass__ = Exposed @Exposed.expose def foo( self ): pass def bar( self ): print "BAR" pass class BotProcess( Process ): @Exposed.expose def addBots( self ): pass p = Process() p.bar() ############# The problem here is that the implementation of 'bar' inside Exposed.__init__ overrides the implementation of bar() in Process, which makes sense I guess seeing as Exposed.__init__() is called after the class has been initialised. It's not a problem for getExposedMethods() seeing as it's not overriden by any derived classes. So what is the accepted way of doing this? Do I need two Exposed classes, one is the metaclass that handles all the static mapping stuff, and another provides base implementations of methods and is what is actually derived from? E.g.: class ExposedMeta( type ): ... class Exposed( object ): ... class Process( Exposed ): __metaclass__ = ExposedMeta ... class BotProcess( Process ): ... Hmmm ... that seems a bit ugly too. If I change the assignments in Exposed.__init__() I guess I can avoid the two-class thing: cls.getExposedMethods = getattr( cls, "getExposedMethods", lambda self: self.s_exposedMethods ) cls.bar = getattr( cls, "bar", lambda self: sys.stdout.write( "bar\n" ) ) That's better, but still ugly. Is there a better way? Thanks for all the help thus far guys, Glen Maric Michaud wrote: > Le jeudi 05 octobre 2006 17:18, [EMAIL PROTECTED] a écrit : > > I guess my solution is slightly less elegant because > > it requires this ugly explicit init call outside the classes that it > > actually deals with, however it is more efficient because the dir() > > pass happens once on module load, instead of every time I want the list > > of exposed methods. > > You can always replace the need of the init method on classes using a > metaclass. > > This demonstrates it with Bruno's expose decorator, but it can be done with > your actual init func too. > > In [6]: class m(type) : > ...: def __init__(self, *a,**kw) : > ...: for name, meth in self.__dict__.items() : > ...: if getattr(meth, '_exposed', False) : > ...: print 'exposed :', name > ...: > ...: > > In [7]: class a(object): > ...: __metaclass__ = m > ...: def f(self) :pass > ...: @expose > ...: def g(self) :pass > ...: > ...: > exposed : g > > In [8]: class b(a) : > ...: @expose > ...: def h(self) :pass > ...: > ...: > exposed : h > > > > > -- > _____________ > > Maric Michaud > _____________ > > Aristote - www.aristote.info > 3 place des tapis > 69004 Lyon > Tel: +33 426 880 097 -- http://mail.python.org/mailman/listinfo/python-list