On Sat, 12 Jan 2008 10:45:25 -0800 (PST) Richard Szopa <[EMAIL PROTECTED]> wrote:
> Hello all, > > I am playing around w/ Python's object system and decorators and I > decided to write (as an exercise) a decorator that (if applied to a > method) would call the superclass' method of the same name before > doing anything (initially I wanted to do something like CLOS > [1] :before and :end methods, but that turned out to be too > difficult). > > However, I cannot get it right (specially, get rid of the eval). I > suspect that I may be misunderstanding something happening between > super objects and __getattribute__ methods. > > Here's my code: > > def endmethod(fun): > """Decorator to call a superclass' fun first. > > If the classes child and parent are defined as below, it should > work like: > > >>> x = child() > >>> x.foo() > I am parent's foo > I am child's foo. > """ > name = fun.__name__ > def decorated(self, *args, **kwargs): > try: > super_object = super(self.__class__, self) There's an apparently common bug here: you don't want to pass super self.__class__, but the class that the method is bound to. The two aren't the same, as an instance of a subclass will have the subclass as self.__class__, and not the current class. So super will return the current class or a subclass of it, meaning (since you invoked this method from self) you'll wind up invoking this method recursively. All of which means your decorator is probably going to have to take the class as an argument. > # now I want to achieve something equivalent to calling > # parent.foo(*args, **kwargs) > # if I wanted to limit it only to this example > > # this doesn't work: in the example, it calls child's foo, > # entering in an eternal loop (instead of calling parent's > # foo, as I would expect). > > # super_object.__getattribute__(name)(*args, **kwargs) > > # this does work, but I feel it's ugly > eval('super_object.%s(*args, **kwargs)' % name) > except AttributeError: > pass # if parent doesn't implement fun, we don't care > # about it > return fun(self, *args, **kwargs) # hopefully none > > decorated.__name__ = name > return decorated > > > class parent(object): > def foo(self): > print 'I am parent\'s foo' > > class child(parent): > @endmethod > def foo(self): > print "I am foo\'s foo." > > if __name__=='__main__': > x = child() > x.foo() > > Can anybody tell me how to call a superclass method knowing its name? The same way you call any object's methods if you know it's name": getattr(super_object, name)(*args, **kwargs) The code seems to work the way you want: >>> x.foo() I am parent's foo I am foo's foo. <mike -- Mike Meyer <[EMAIL PROTECTED]> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. -- http://mail.python.org/mailman/listinfo/python-list