On Tue, 2009-09-29 at 21:15 -0700, Rich Healey wrote: > However: > > def callonce(func): > def nullmethod(): pass > def __(): > return func() > func = nullmethod > return ret > return __ > > @callonce > def t2(): > print "T2 called" > t2() > > Gives me: > > C:\tmp\callonce>callonce.py > Traceback (most recent call last): > File "C:\tmp\callonce\callonce.py", line 27, in <module> > t2() > File "C:\tmp\callonce\callonce.py", line 12, in __ > return func() > UnboundLocalError: local variable 'func' referenced before assignment > > Any ideas on why? This looks like a bug to me, but I'm quite new to > this style of programming so it may be some nuance I'm not aware of.
I'm not following your logic. There is no check to see if func is already called. Moreover, you are replacing func which is not recommended. A decorator is supposed to "decorate" func, not replace it. I think what is happening here is func = nullmethod is being assigned at definition time, not at runtime, so by the time you've defined __() func is no longer there, so Secondly, if nullmethod returns nothing, why not just return nothing in __() instead of creating a new function that does nothing. Thirdly, 'return ret' is never called. Because you return out of __() in the first line of the function. Fourthly, 'ret' is never defined, so even if it were run you would get an undefined error. But what I think is happening is since you have effectively overriden func (t2) with nullmethod it gets 'lost' by the time the __() is actually called. I haven't looked closely but you should be able to see what's happening in a debugger. What you really want to do is something like this: def callonce(func): func.called = False def dec(*args, **kwargs): if func.called: return func.called=True return func(*args, **kwargs) return dec @callonce def t2(): print 't2() Called' >>> t2() t2() Called >>> t2() >>> -- http://mail.python.org/mailman/listinfo/python-list