Decorators, with optional arguments

Thomas Jollans thomas at jollans.com
Fri Jul 2 14:55:26 EDT 2010


On 07/02/2010 07:41 PM, Stephen Hansen wrote:
> Okay, so!
> 
> I actually never quite got around to learning to do deep and useful
> magic with decorators. I've only ever done the most basic things with
> them. Its all been a little fuzzy in my head: things like what order
> decorators end up being called in if there's more then one, etc.
> 
> But in my current situation, what I'm wanting to do is have a decorator
> that wraps a function but which takes an *optional* argument, and sets
> that argument as an attribute on said function if its there.
> 
> Here's what some tweaking and playing around has gotten me, as a recipe:
> 
>     import functools
> 
>     def my_decorator(arg):
>         if callable(arg): # Stuck on 2.5. Leavemealone. :)
>             protocol = None
>         else:
>             protocol = arg
> 
>         def wrap(fn):
>             print "Wrapping."
>             fn.protocol = protocol
> 
>             @functools.wraps(fn)
>             def wrapper(*args, **kwargs):
>                 print "Calling."
>                 result = fn(*args, **kwargs)
>                 print "Called."
>                 return result
> 
>             return wrapper
> 
>         if not protocol: # argument-less decorator
>             print "Calling wrap."
>             return wrap(arg)
>         else:
>             print "Returning wrap."
>             return wrap

Looks good! You may still want to use functools.update_wrapper or
functools.wraps on "wrap".

PS: if you weren't stuck on 2.5, but were using 3.x, there's all kinds
of fun stuff you could do with function annotations ;-)

> 
> To be used as:
> 
>     class Thing(object):
>         @expose
>         def test1(self, arg1):
>             return arg1
> 
>         @expose("testing")
>         def test2(self, arg2):
>             return arg2
> 
> So, my question: am I doing this right? :) Some play-through testing
> appears to work. But, the dizzying array of nested def's up there leaves
> me a bit dazed, so I'm wondering if there's a simpler way to accomplish
> what I'm trying to do.
> 
> Thanks.
> 




More information about the Python-list mailing list