2

I have nested a function definition bar() inside another function foo(). Now I am trying to access a variable located in the outer function foo() from the nested function bar(). This however doesn't work because of the scoping rules (see error traceback below).

I am looking for something similar to the global keyword, which however only enables me to access global variables, whereas this is some kind of semi-global variable.

Here's example code:

def foo():
    i = 0
    def bar():
        # how can I get access to the variable from enclosing scope?
        i += 1
    bar()

foo()

The output is:

$ python test.py
Traceback (most recent call last):
  File "test.py", line 7, in <module>
    foo()
  File "test.py", line 5, in foo
    bar()
  File "test.py", line 4, in bar
    i += 1
UnboundLocalError: local variable 'i' referenced before assignment
moooeeeep
  • 31,622
  • 22
  • 98
  • 187

2 Answers2

7

You need the nonlocal statement instead of global.

i is clearly not global, but it is also not local to foo. It is local to __init__. Thus, in order to access it, declare it nonlocal.

Unfortunately, nonlocal ist python3 only. You can simulate it via closure, but that'd get pretty ugly.

ch3ka
  • 11,792
  • 4
  • 31
  • 28
3

Here is your work around:

class Test(object):
    def __init__(self):
        i = [0]
        def foo():
            i[0] += 1
        foo()
        print i[0]

t = Test()

This would be a use case for the nonlocal keyword, instead of global but that is only available as of Python 3.

jsbueno
  • 99,910
  • 10
  • 151
  • 209
  • +1 for the Python 2.x workaround. Surprisingly container types are unaffected from this. – moooeeeep Apr 17 '12 at 15:20
  • They *are* affected. What saves you here, is that the scoping rules DO allow READ access. Technically, you do not WRITE to i, you write to i[0]... – ch3ka Apr 17 '12 at 16:33
  • Interesting, found [this answer](http://stackoverflow.com/a/293097/1025391) to explain this very well. – moooeeeep Apr 18 '12 at 07:54