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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Ponkadoodle
  • 5,777
  • 5
  • 38
  • 62

3 Answers3

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

Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
1

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

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
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
Community
  • 1
  • 1
tutuDajuju
  • 10,307
  • 6
  • 65
  • 88