I like to think of decorators with arguments as decorator factory functions. I try and unroll them as much as possible... I have some decorators that work like so (and please note that the wraps and returns_as_output are separate so that I can mutate the behavior as needed, if you just wanted a single decorator this could be condensed):
def wrap(f, wrapping_function, *args): argspec = inspect.getargspec(f) without_defaults = len(argspec.args) - len(argspec.defaults or []) f._args = {} f._varkw = [] f._arg_defaults = (None,) * without_defaults + (argspec.defaults or tuple()) for arg in args: if arg in argspec.args: f._args[arg] = argspec.args.index(arg) else: if argspec.keywords: f._varkw.append(arg) return decorator.decorator(wrapping_function, f) def return_as_output(output_f): def func(f, *args, **kwargs): new_args = list(args) for (dict_name, index) in f._args.items(): if len(args) > index: new_args[index] = output_f(args[index]) else: d = f._arg_defaults[index] kwargs[dict_name] = output_f(kwargs.pop(dict_name, d)) for dict_name in f._varkw: kwargs[dict_name] = output_f(kwargs.pop(dict_name, None)) return f(*new_args, **kwargs) return func def iterables(*args): ''' Decorator that guarantees that the named arguments will be iterable. ''' as_iterables = return_as_output(iter_) return lambda f: wrap(f, as_iterables, *args) Just as an example... I have a family of decorators that check compliance with abstract base classes, then try to mutate variables to provide it if duck typing would fail. I don't know if this helps, it is kind of convoluted, but hopefully it gives you another example to work from.
-- http://mail.python.org/mailman/listinfo/python-list