…so the challenge is to create a dectorator that accepts either no parameters, or accepts any number of keyword parameters. That is
def woo() :
def pop() :
The problem is, for woo, the decorator is going to get called once with zing(woo), and the result should be a function with the signature of the target function.
For pop, it’s more complicated:
+ first, call with zing(**kwargs), expect build(function) back
+ call build(pop), expect a function with the same signature as the original
+ call that function
So I took a hint from the web, and based the logic on the type of the first parameter, if there is one. Then I switched it around to take advantage of the fact that there will either be one argument (the target function), or else there will be keyword arguments. But not both.
If there are keywords, the code resolves them and bakes them into a closure. Which is itself inside a closure.
def woop(*args,**kwargs): if len(args) and callable(args) : return _wrap(args,'simple') else : extra = kwargs.get('extra','nope') def build(target): return _wrap(target,extra) return build def _wrap(target,extra): def woop_woop(that,a): return 'woop:' + target(that,a) + '.' + extra + ':woop' return woop_woop class Ping(object): @woop def zong(self,a): return a @woop(extra='zzz') def zing(self,a): return a @woop(sleep='woo') def nope(self,a): return a p = Ping() print p.zong('aaa') print p.zing('bbb') print p.nope('ccc')