So I'm having a very strange error right now. I found where it happens, and here's the simplest code that can reproduce it.
def cause_an_error():
some_var = False
def some_nested_func():
print some_var
#some_var = True
some_nested_func()
>>> cause_an_error()
False
If you run it as-is, it prints "False". But if you uncomment that line, it gives an error:
Traceback (most recent call last):
File "<pyshell#224>", line 1, in <module>
cause_an_error()
File "<pyshell#223>", line 6, in cause_an_error
some_nested_func()
File "<pyshell#223>", line 4, in some_nested_func
print some_var
UnboundLocalError: local variable 'some_var' referenced before assignment
Notice the error occurs on the line that worked just fine before.
Any ideas what causes this and how I can fix this? I'm using Python 2.6.1.
-
very similar to this stackoverflow.com/questions/2516652/…Ruggero Turra– Ruggero Turra2010年05月22日 10:06:14 +00:00Commented May 22, 2010 at 10:06
3 Answers 3
The inner function, some_nest_func, has its own scope, and the fact that you are assigning to some_var somewhere within that scope makes some_var local to that scope. This has the effect of hiding the some_var assigned in the outer function. They are two different variables.
The upshot of all this is that you are printing some_nest_func's version of some_var before you assign to it.
If you need to manipulate some variable both in and outside the inner function, there isn't a clean way to it, AFAIK. A simple work-around is to replace the variable with a single-element array and manipulate that isn't (don't assign to the array variable, of course).
3 Comments
This can't be fixed in 2.x without refactoring the code. 3.x adds nonlocal to solve this.
Comments
You can do this by changing a value of a referenced (read mutable) variable such as dict, although ugly, this solution (transcribed from an answer to a similar question) should work:
def avoid_an_error():
D = {"some_var": False}
def some_nested_func():
D["some_var"] = True
print D["some_var"]
some_nested_func()
>>> avoid_an_error()
True