So here is some weird / interesting approach when you only need to change Foo , the idea here is to create a new decorator that delays baz decoration until the function is first called with some reason to cache on the name class so that it happens only once.
Note that this also includes a dummy implementation for baz that simply prints the frob argument that was provided, but this approach should work fine, without having to modify baz :
def baz(frob): def deco(func): def wrapped(*args, **kwargs): print('frob:', frob) return func(*args, **kwargs) return wrapped return deco def newdeco(func): def wrapped(self, *args, **kwargs): if not hasattr(wrapped, 'cache'): wrapped.cache = {} cls = self.__class__.__name__ if cls not in wrapped.cache: wrapped.cache[cls] = baz(frob=getattr(self.__class__, 'bar'))(func) wrapped.cache[cls](self, *args, **kwargs) return wrapped class Foo: bar = None @newdeco def oof(self): pass class Rab(Foo): bar = 'zab' f = Foo() f.oof() r = Rab() r.oof()
I also had to add the self argument to oof based on the assumption that oof is a method, if baz also converts the function to a static method, I'm not sure if this approach will work.
Andrew Clark
source share