At work, my friend Jon and I were looking into timing the various decorators in the app ( We didn’t want to manually modify each decorator we were hoping to time. I ended up exploring the possibility of decorating decorators. It was an approach that could allow us to make the minimum modification to a decorator (just slapping on the timing decorator) and with very little duplicate code.

Here’s the basic approach:

import time
from functools import wraps

def timed(decorator):
    def wrapped_decorator(func):
        recorded_time = []
        def timed(func):
            def timed_func(*args, **kwargs):
                start = time.time()
                rv = func(*args, **kwargs)
                if recorded_time:
                    outer_time = time.time() - start
                    print 'Decorator time: ', outer_time - recorded_time.pop()
                    recorded_time.append(time.time() - start)
                return rv
            return timed_func
        return timed(decorator(timed(func)))
    return wrapped_decorator
def upper(func):
    def wrapped():
        return func().upper()
    return wrapped
def hello():
    return 'hello'
if __name__ == '__main__':
    print hello()