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
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to