On Mon, 03 Aug 2009 19:59:23 +0000, kj wrote: > I want to write a decorator that, among other things, returns a function > that has one additional keyword parameter, say foo=None. > > When I try > > def my_decorator(f): > # blah, blah > def wrapper(*p, foo=None, **kw): > x = f(*p, **kw) > if (foo): > # blah, blah > else > # blah blah > return wrapper > > ...i get a syntax error where it says "foo=None". I get similar errors > with everything else I've tried. > > Is is possible to do this in Python?
Have you tried this under Python 2.6 or 3.0? I've run into similar issues, because you can't have keyword-only arguments in Python 2.5 :( My solution was to create a decorator that faked them. The docstring is longer than the decorator itself. from functools import wraps def keywords(**defaults): """Return a decorator which decorates a function to accept keyword arguments. Python 2.5 and earlier don't allow keyword-only arguments for non-builtin functions. The obvious syntax: def func(x, *args, key=None, word='parrot'): is not permitted. As a work-around, write your function something like the following example: >>> @keywords(key=None, word='parrot') ... def func(x, y=0, *args, **kwargs): ... # Inside the function, we can guarantee that kwargs['key'] and ... # kwargs['word'] both exist, and no other keys. ... print "x=%s, y=%s, args=%s" % (x, y, args) ... if kwargs['key'] is None: msg = "kwargs['key'] is None" ... else: msg = "kwargs['key'] is something else" ... msg += " and kwargs['word'] is %r" % kwargs['word'] ... print msg ... When you call func, if you don't provide a keyword-only argument, the default will be substituted: >>> func(1, 2, 3, 4) x=1, y=2, args=(3, 4) kwargs['key'] is None and kwargs['word'] is 'parrot' >>> func(1) x=1, y=0, args=() kwargs['key'] is None and kwargs['word'] is 'parrot' Naturally you can provide your own values for keyword-only arguments: >>> func(1, 2, 3, word='spam') x=1, y=2, args=(3,) kwargs['key'] is None and kwargs['word'] is 'spam' >>> func(1, 2, 3, word='spam', key=len) x=1, y=2, args=(3,) kwargs['key'] is something else and kwargs['word'] is 'spam' If you pass an unexpected keyword argument, TypeError is raised: >>> #doctest:+IGNORE_EXCEPTION_DETAIL ... func(1, 2, 3, 4, keyword='something') Traceback (most recent call last): ... TypeError: ... """ def decorator(func): """Decorate func to allow keyword-only arguments.""" @wraps(func) def f(*args, **kwargs): for key in kwargs: if key not in defaults: raise TypeError( "'%s' is an invalid keyword argument for " \ "this function" % key ) d = defaults.copy() d.update(kwargs) return func(*args, **d) return f return decorator (Copy and pasted from working code, but I make no guarantee that it will have survived the process in working order!) -- Steven -- http://mail.python.org/mailman/listinfo/python-list