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. > -- http://mail.python.org/mailman/listinfo/python-list