Calling instance methods from a decorator

Diez B. Roggisch deets at nospam.web.de
Fri May 30 13:40:17 EDT 2008


Kirk Strauser schrieb:
> I'm trying to write a decorator that would do something like:
> 
> def trace(before, after):
>     def middle(func):
>         def inner(*args, **kwargs):
>             func.im_self.debugfunction(before)
>             result = func(*args, **kwargs)
>             func.im_self.debugfunction(after)
>             return result
>         return inner
>    return middle
> 
> class Foo(object):
>     def __init__(self, myname):
>         self.name = myname
> 
>     def debugfunction(self, message):
>         print 'Instance %s says: %s' % (self.name, message)
> 
>     @trace('calling', 'finished')
>     def bar(self, arg):
>         print arg
> 
>>>> Foo('snake').bar(123)
> Instance snake says: calling
> 123
> Instance snake says: finished
> 
> The gotcha seems to be that there's no way to get to 'self' from within the
> "inner" function, since func will only have the "normal" attributes:
> 
>>>> print dir(func)
> ['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
> 
> There's no nice im_self to bounce off of or anything.  I seem to be going
> about this all wrong.  What's a good approach to get the desired effect?

Of course you can get the self - just use the first paramter, because it 
  *is* self. Self is just a parameter - nothing special.

Alternatively, declare inner like this:

def inner(self, *args, **kwargs):
     ...
     try:
        return func(self, *args, **kwargs)
     finally:
        ....


Note the additional try/finally. It's got nothing todo with your 
original problem - but you should use it to guarantee that your trace 
gets called when leaving the call.

Diez



More information about the Python-list mailing list