
On Mon, Jun 13, 2011 at 9:12 PM, Jan Kaliszewski <zuo@chopin.edu.pl> wrote:
On second thought: no. I mean: no -- for a separate syntax construct with limited usage possibilities (see: cases mentioned by Steven); yes -- for language improvements that would make possible one of the solutions:
1. A real decorator: a) quasi-argument-locals-based (names could be used to read injected value and later could be rebound, like arguments);
Forgive me if im wrong but i believe that this is possible without any language changes using pure python. this is my attempt at it:
from inspect import getfullargspec as argspec
def makeLocal(**localArgs): def decorator(func): if (_anyConflicts(func, localArgs)): raise Exception("abiguity in names")
def inner(*args, **kwargs): if (any(Larg in kwargs.keys() for Larg in localArgs.keys())): raise NameError("no resetting locals")
## used to restore __globals__ i think this is alright since ## iirc __globals__ only holds references anyway frmglobals = func.__globals__.copy() func.__globals__.update(localArgs) ret= func(*args, **kwargs) func.__globals__.clear() func.__globals__.update(frmglobals) return ret
inner.__doc__=func.__doc__ inner.__name__=func.__name__ return inner return decorator
def _anyConflicts(func, localArgs): fa = argspec(func) for Larg in localArgs: if (Larg in fa.args or Larg in fa.kwonlyargs or Larg in fa): return True return False
this uses a closure to hold the values of the injected values and hides them all test pass exactly as if the values were defined with makeLocals were globals within the function but all act as if they are locals outside of it. this means that if we define this this
@makeLocal(aList=list()) def add_and_print(arg): aList.append(arg) print(aList)
and run
add_and_print(1) #it prints [1] add_and_print(33) #prints [1,33]
if we try this
print(aList) we get a NameError
and if we try this
aList=['this','is','a','different','list'] add_and_print(66)#prints [1,33,66] print(aList) ['this','is','a','different','list']
anInt=33 def increment(): anInt+=1 foo(22)
all problems with global values still apply with this however. for example just as throws a UnboundLocalError so does
@makeLocal(anInt=33) def increment(): anInt+=1
so what do you think? --Alex