understanding decorators in python
Question: I am having an object I cant touch, but would like to log the method calls. I
don't really understand decorators, but I was wondering if there is a more
elegant way to do something like this

    
    
    import pprint
    
     class myTest(object):
        def __init__(self):
            self.a = 1
        def test(self, **kwargs):
            for k, v in kwargs.items():            
                setattr(self, k, v)   
    
    def wrap(o, method, **kwargs):
        for k, v in kwargs.items():
            print '%s set to %s' %(k, v)
            getattr(o, method)(**kwargs)
    
    
    o = myTest()
    d = {'b':2,'c': 3}
    
    wrap(o, 'test', **d)
    pprint.pprint(vars(o))
    

such that I can decorate a regular method call and do it somehow like this:

    
    
    @mydecorator
    o.test(**d)
    

and would get a similar result. Then I would not have to replace all the
method calls in the script


Answer: The question mentioned in the comments has some excellent explainations of
decorators, so you should read that first - [How can I make a chain of
function decorators in Python?](http://stackoverflow.com/questions/739654/how-
can-i-make-a-chain-of-function-decorators-in-python)

As to your specific question. As you can't touch the `myTest` object
definition, you can just change it's methods at runtime! You can do this just
to your instance:

    
    
    import pprint
    
    class myTest(object):
        def __init__(self):
            self.a = 1
        def test(self, **kwargs):
            for k, v in kwargs.items():            
                setattr(self, k, v)   
    
    def log_calls(fn):
        def wrapped(*args, **kwargs):
            print '%s called with args %s and kwargs %s' % (repr(fn), repr(args), repr(kwargs))
            fn(*args, **kwargs)
        return wrapped
    
    o = myTest()
    o.test = log_calls(o.test) # equivalent to applying the decorator at method
                               # definition, but only applies to this instance of myTest
    
    d = {'b':2, 'c':3}
    o.test(**d)
    pprint.pprint(vars(o))
    

Outputs:

    
    
    <bound method myTest.test of <__main__.myTest object at 0x0000000002EE07F0>> called with args () and kwargs {'c': 3, 'b': 2}
    {'a': 1, 'b': 2, 'c': 3, 'test': <function wrapped at 0x0000000002EDDEB8>}
    

Or modify the class itself:

    
    
    myTest.test = log_calls(myTest.test)
    o = myTest()
    
    d = {'b':2, 'c':3}
    o.test(**d)
    pprint.pprint(vars(o))
    

This is called monkey patching - you can find some more info here [What is
monkey patch?](http://stackoverflow.com/questions/5626193/what-is-monkey-
patch)

