By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,846 Members | 1,836 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,846 IT Pros & Developers. It's quick & easy.

Calling instance methods from a decorator

P: n/a
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?
--
Kirk Strauser
The Day Companies
Jun 27 '08 #1
Share this Question
Share on Google+
2 Replies


P: n/a
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
Jun 27 '08 #2

P: n/a
At 2008-05-30T17:40:17Z, "Diez B. Roggisch" <de***@nospam.web.dewrites:
Of course you can get the self - just use the first paramter, because it
*is* self. Self is just a parameter - nothing special.
If I blame it on being a long week, can I keep my geek card?
--
Kirk Strauser
The Day Companies
Jun 27 '08 #3

This discussion thread is closed

Replies have been disabled for this discussion.