In Python, you can declare a function within another function and the scope of local variables in the outer function carry through to the inner function. However, you have to be careful with the re-assignment of the variable inside of the inner function due to some funkiness that may or may not be a bug (I say its a bug but who am I?)
Take the following example:
>>> def top_f(f): >>> return f() >>> >>> def outer_f(v=None): >>> print "v in outer = %s" % v >>> def inner_f(): >>> print "v in inner = %s" % v >>> return top_f(inner_f) >>> >>> outer_f("see me?") >>> v in outer = see me? >>> v in inner = see me?
As expected the variable is visible within the inner function. Now look at the above example with one minor modification. We will re-assign the value of the variable in a nested fashion:
>>> def top_f(f): >>> return f() >>> >>> def outer_f(v=None): >>> print "v in outer = %s" % v >>> def inner_f(): >>> v = v + " now" >>> print "v in inner = %s" % v >>> return top_f(inner_f) >>> >>> outer_f("see me?") >>> v in outer = see me? >>> Traceback (most recent call last): ... >>> UnboundLocalError: local variable 'v' referenced before assignment
Whaaa?!?
In my opinion, the construct of v = v + " now" should be allowed as it is everywhere else in code and behave as expected. However, obviously something is amiss on the stack (or would that be heap?) – I care not to speculate as such low level memory thinking makes my head hurt and if I wanted to deal with such things I would code in C or worse, assembly!
This behaviour is present in v. 2.4 and 2.5. I have not tested in v. 2.6 or 3.0
same problem here. googled for ‘python local scope’ and found your article as first match, while it explains the same problem I have in my code
looks like you are not alone in this assumption that the code looks workable, while it is not
I think what’s happening here is that, as soon as you make an assignment, the variable becomes local. The problem is that it’s becomes local on the whole inner function scope, even before the assignment is made.
If you just add v = ‘a’ at the end of inner_f in the first example you get the same kind of error.