cts.private.ya...@gmail.com wrote: > I'd like to use closures to set allow a subroutine to set variables in its > caller, in leu of pointers.
"leu"? Must be a Fench word ;) > But I can't get it to work. I have the > following test pgm, but I can't understand its behaviour: > > It uses a function p2() from the module modules.closure1b: > > def p2 (proc): > proc ("dolly") > > I thought the following worked like I expected it to: > > > from modules.closures1b import p2 > > def p1(msg1): > msg3 = "world" > print "p1: entered: ", msg1 > def p11(msg2): > print "p11: entered: ", msg2 > print msg1 + msg2 + msg3 > print p2 (p11) > > p1('hello') > > $ python closures1c.py > p1: entered: hello > p11: entered: dolly > hellodollyworld > None > > In other words, p1() is passed "hello" for msg1, "world" goes to the local > msg3 and then p11() is invoked out of a remote module and it can access > not only its own argument (msg2) but also the variables local to p1(): > "hellodollyworld". > > But if I try to set the variable local to p1(), all of a sudden python > seems to forget everything we agreed on. > > If I add this line to the script above: > msg3 = "goodbye" > as follows: > > from modules.closures1b import p2 > > def p1(msg1): > msg3 = "world" > print "p1: entered: ", msg1 > def p11(msg2): > print "p11: entered: ", msg2 > print msg1 + msg2 + msg3 > msg3 = "goodbye" # <- new > print p2 (p11) > > p1('hello') > > then all of a sudden, I get this: > > p1: entered: hello > p11: entered: dolly > Traceback (most recent call last): > File "closures1c.py", line 13, in <module> > p1('hello') > File "closures1c.py", line 11, in p1 > print p2 (p11) > File "/home/mellman/eg/python/modules/closures1b.py", line 2, in p2 > proc ("dolly") > File "closures1c.py", line 9, in p11 > print msg1 + msg2 + msg3 > UnboundLocalError: local variable 'msg3' referenced before assignment > > > Huh? msg3 isn't more referenced than it was before! > > Can anyone explain this to me? You picked the most obnoxious variable names I can think of, but the actual problem is simple: Python statically determines the scope of a variable. If you rebind a name it becomes a local variable unless you explicitly declare it as global or -- in Python 3 -- as nonlocal. For example: Wrong: >>> def outer(): ... n = 0 ... def inner(): ... print(n) ... n += 1 ... return inner ... >>> outer()() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in inner UnboundLocalError: local variable 'n' referenced before assignment With nonlocal declaration (Python 3 only): >>> def outer(): ... n = 0 ... def inner(): ... nonlocal n ... print(n) ... n += 1 ... return inner ... >>> f = outer() >>> f() 0 >>> f() 1 >>> f() 2 With a mutable variable as a pseudo-namespace (workaround for Python 2): >>> def outer(): ... n = [0] ... def inner(): ... print n[0] ... n[0] += 1 ... return inner ... >>> f = outer() >>> f() 0 >>> f() 1 -- http://mail.python.org/mailman/listinfo/python-list