1. 2010
    Aug
    07

    More Python voodoo: optional-argument decorators

    I’ve just been doing something that probably should never be done in Python (again), and I figured it might be useful to record this little snippet for posterity. Many Python programmers are probably familiar with decorators, which modify functions by wrapping them with other functions. For example, if you want to print ‘entering’ and ‘exiting’ to trace when a function’s execution begins and ends, you could do that with a decorator:

    def trace(func):
        def wrapper(*args, **kwargs):
            print 'entering'
            func(*args, **kwargs)
            print 'exiting'
        return wrapper
    
    @trace
    def f(a,b):
         print 'in f: ' + str(a) + ',' + str(b)
    

    Note that in practice there are better ways to do this, but it’s just an example.

    Anyway, it’s also possible to customize the behavior of decorator itself by providing arguments, for instance if you wanted to print different strings instead of ‘entering’ and ‘exiting’. But in that case, your “decorator” function is actually a wrapper that creates the real decorator and returns it:

    def trace(enter_string, exit_string):
        def _trace(func):
            def wrapper(*args, **kwargs):
                print enter_string
                func(*args, **kwargs)
                print exit_string
            return wrapper
        return _trace
    
    @trace('calling f', 'returning')
    def f(a,b):
         print 'in f: ' + str …