stesteve stesteve - 4 years ago 158
Python Question

Using global name in a nested function

As I understand the global statement in the code below, it should prevent function_two from rebinding the name test and instead modify test in function_one. However, I get NameError: global name 'test' is not defined.

def function_one():
test = 1
def function_two():
global test
test += 1
function_two()
print test
function_one()


I have looked and I can't find an example like this. What am I missing?

Answer Source

Python 2 does not support the concept of a non-local. Closures (accessing test from a parent function) only support read access, not assignment in Python 2.

The global keyword really does mean global, e.g. that the name lives in the module (global) namespace. The namespace of the function_one() function is not global, it is local (to that function).

In Python 3, you can mark a name as nonlocal, which would make your example work as expected. See PEP 3104 - Access to Names in Outer Scopes.

In Python 2, you'll have to resort to tricks instead. Make the name an attribute of the nested function, for example. 'reading' the function object as a closure is allowed, as is setting attributes on such closed-over objects:

def function_one():
    def function_two():
        function_two.test += 1

    function_two.test = 1
    function_two()

    print test

Another trick is to use a mutable object, such as a list or a dictionary. Again, you are only reading the closed-over name, then altering the resulting object directly:

def function_one():
    test = [1]

    def function_two():
        test[0] += 1

    function_two()

    print test[0]
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download