In [1]:
def add(a,b):
    return a+b

In [2]:
add(3,4)


Out[2]:
7

What if we want to log when that function is called?


In [3]:
def logged_add(a, b):
    print '### %s(%r, %r)' % ('add', a, b)
    result = add(a, b)
    print '### %s(%r, %r) --> %r' % ('add', a, b, result)
    return result

could change all calls to this -- blech!

so instead write a wrapper:


In [5]:
def logged(func):
    def wrapper(a, b):
        print '### %s(%r, %r)' % (func.func_name, a, b)
        result = func(a, b)
        print '### %s(%r, %r) --> %r' % (func.func_name, a, b, result)
        return result
    return wrapper

re-define add...


In [6]:
add = logged(add)

In [6]:
add(3,4)


### add(3, 4)
### add(3, 4) --> 7
Out[6]:
7

And use it for other functions, too:


In [7]:
def subtract(a, b):
    """subtract() subtracts two things"""
    return a - b
subtract = logged(subtract)

In [8]:
subtract(7,4)


### subtract(7, 4)
### subtract(7, 4) --> 3
Out[8]:
3

Make it more general -- to take any number of arguments:


In [9]:
def logged(func):
    def wrapper(*args):
        print '### %s(%s)' % (func.func_name, args)
        result = func(*args)
        print '### %s(%s) --> %r' % (func.func_name, args, result)
        return result
    return wrapper

A function with one argument:


In [10]:
def even(a):
    """even() returns True if the value is even"""
    return a % 2 == 0
even = logged(even)

In [11]:
even(3)


### even((3,))
### even((3,)) --> False
Out[11]:
False

In [12]:
even(4)


### even((4,))
### even((4,)) --> True
Out[12]:
True

In [12]:


In [ ]: