
-----Original Message----- On 8 Oct 2007, at 10:57, Arnaud Delobelle wrote:
On Mon, October 8, 2007 4:33 am, Adam Atlas wrote:
When writing decorators especially when it's one that needs arguments other than the function to be wrapped, it often gets rather ugly...
[...]
Whhy not create a (meta-)decorator to do this? Something like: [...]
Following up post from 10/8/07.
To follow up on my untested suggestion, here's one that is tested:
# This metadecorator hasn't changed
def decorator_withargs(decf): def decorator(*args, **kwargs): def decorated(f): return decf(f, *args, **kwargs) return decorated return decorator
This is equivalent to: (1) decorator_withargs= partial( partial, prepartial ) , where prepartial is roughly the same as partial as you might expect: (2) 1 def prepartial(func, *args, **keywords): 2 def newfunc(*fargs, **fkeywords): 3 newkeywords = keywords.copy() 4 newkeywords.update(fkeywords) 5 return func(*(fargs+ args), **newkeywords) 6 newfunc.func = func 7 newfunc.args = args 8 newfunc.keywords = keywords 9 return newfunc Partial is the same outside of line 5: (3) 5 return func(*(args + fargs), **newkeywords) Results are the same: -> f 1 f -> 2 2 Intriguing.
# Here's how to use it to create a decorator
@decorator_withargs def mydec(f, before='entering %s', after='%s returns %%s'): before = before % f.__name__ after = after % f.__name__ def decorated(*args, **kwargs): print before result = f(*args, **kwargs) print after % result return result return decorated
# Now I can decorate a function with my new decorator
@mydec(before='-> %s', after='%s -> %%s') def f(x): print x return x+1
Then
f(1) -> f 1 f -> 2 2
-- Arnaud