modifying method behaviour

Nicodemus nicodemus at globalite.com.br
Tue Aug 26 20:46:01 EDT 2003


Craig Zoretich wrote:

>Hi,
>
>I am trying to modify the behaviour of a method so it will
>automatically log information for me.  I have been able to do this
>with functions by using the code that was kindly submitted to this
>newsgroup:
>
>
>>class logger:
>>    def  __init__(self, func):
>>         self.func = func
>>    def __call__(self, *args):
>>        print "Called: %s with args %s" % (self.func.func_name, args)
>>        return self.func(*args)
>>
>>def myfunc(a): return a
>>
>>myfunc = logger(myfunc)
>>
>
>This code works great for functions, but it doesn't work too well for
>methods within a class.  Here's an example of my code:
>
>
>>class logger:
>>    def  __init__(self, func):
>>         self.func = func
>>    def __call__(self, *args):
>>        print "Called: %s with args %s" % (self.func.func_name, args)
>>        return self.func(self, *args)
>>
>>class myClass:
>>    def myfunc(self, a): return a
>>
>>    myfunc = logger(myfunc)
>>
>
>What happens is that the "self" argument in myClass.myfunc is being
>filled with an instance of the logger class, so it doesn't see any of
>the attributes of "myClass".   Is there a simple way of tweeking this
>code, or do I need to redesign how I am doing this?
>

Use the new descriptor protocol:



class logmethod(object):

    def __init__(self, func):
        self.func = func

    def __get__(self, obj, class_):
        def logger(s, *args, **kwargs):
            result = self.func(s, *args, **kwargs)
            params = [repr(x) for x in args]
            params += ['%s=%r' % (name, value) for name, value in 
kwargs.items()]
            print 'LOG: %s(%s)' % (self.func.__name__, ', '.join(params))
            return result
        return logger.__get__(obj)



class C(object):

    def foo(self, *args, **kwargs):
        print 'foo called!'
        print self.x
        print args
        print kwargs

    foo = logmethod(foo)


c = C()
c.x = 12
c.foo(1, 2, msg="Hello!") 


This script will print:

foo called!
12
(1, 2)
{'msg': 'Hello!'}
LOG: foo(1, 2, msg='Hello!')


To learn more about descriptors, read the excelent article by Raymond 
Hettinger:
http://users.rcn.com/python/download/Descriptor.htm

HTH,
Nicodemus.






More information about the Python-list mailing list