2

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.

1

3 Answers 3

1

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).

Sign up to request clarification or add additional context in comments.

3 Comments

That makes sense to me. But shouldn't the non-local variable only be shadowed after the assignment?
The shadowing happens at compile time. If Python finds an assignment anywhere within the scope, all references become local.
I've amended my answer. Also see Ignacio's answer for Python 3.0.
1

This can't be fixed in 2.x without refactoring the code. 3.x adds nonlocal to solve this.

Comments

0

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.