Le Friday 23 May 2008 04:28:22 [EMAIL PROTECTED], vous avez écrit : > Hi, > I would like to create a Decorator metaclass, which automatically > turns a class which inherits from the "Decorator" type into a > decorator. > A decorator in this case, is simply a class which has all of its > decorator implementation inside a decorator() method. Every other > attribute access is being proxied to decorator().getParent(). > > ... > > ------------------------------------------------------- > Unfortunately this does not work. The newly defined __init__ method > inside __new__, does a call to impl(*args, **dargs). However, since > the HBar.__init__ calls the Decorator.__init__ method, but the > HBar.__init__ method no longer resides inside HBar, but rather inside > HBarImpl (which is no longer a subtype of Decorator), the compiler > complains that Decorator.__init__ is not being called with a Decorator > instance as its first argument (which is true). > I tried changing the definition of impl inside __new__ to have > Decorator as one of its bases, but then for some reason impl(*args, > **dargs) asks for 4 arguments (just like __new__) and I have no clue > as to why that happens. > > Any help on this? >
The problem with kind of design is that you must break the rules of class inheritance, and it seems like a strange idea to implement decorators by inheritance. Of course you could do all sort of magic with python, but what is your goal ? In your example, should the implementation types inherit from each other ? In that case, do you want to preserve the same semantic for __init__ as in standard python class (this could be a hard job) ? This quick fix seems to work with your example, but add extra magic to automatically call the super __init__ of the parent implementation, this could be a bad idea, use with caution ! (I still think it's a bad design, using composition and proxy classes is much more simple and clear) class DecoratorType(type): def __new__(cls, name, bases, dct): # create a new class which will store all of the implementation parent_impl_type = bases[0] is object and object \ or bases[0]._impl_type impl = type('%sImpl'%name,(parent_impl_type,),dict(dct)) dectype = type.__new__(cls, name, bases, {'_impl_type' : impl }) # update the old class to implement this implementation def __init__(self, *args, **dargs): print args, dargs new_impl = impl(*args, **dargs) super(dectype._impl_type, new_impl).__init__(*args, **dargs) object.__setattr__(self, '_impl', new_impl) def decorator(self): return object.__getattribute__(self,'_impl') def __getattribute__(self, attr): if attr=="decorator": return object.__getattribute__(self,'decorator') return getattr(object.__getattribute__( self, 'decorator')(), attr) dectype.__init__ = __init__ dectype.decorator = decorator dectype.__getattribute__ = __getattribute__ return dectype class Decorator(object): __metaclass__ = DecoratorType class HBar(Decorator): def __init__(self, number): print 'hb:', number self._number = number def inc(self): self._number += 1 def p(self): print self._number class HBar2(HBar) : def __init__(self, number): print 'hb2:', number self._hb2 = number def inc2(self): self._hb2 += 1 def p2(self): print self._hb2 hbar = HBar(10) for each in dir(hbar.decorator()): print each hbar.decorator().p() hbar.decorator().inc() hbar.decorator().p() hb2 = HBar2(5) hb2.p() hb2.p2() hb2.inc() hb2.p() hb2.p2() hb2.inc2() hb2.p() hb2.p2() -- _____________ Maric Michaud _____________ -- http://mail.python.org/mailman/listinfo/python-list