views:

1234

answers:

4

What does it do, in Python 3.0? There's no documentation on the official Python website and help("nonlocal") does not work, either.

+7  A: 

In short, it lets you assign values to a variable in an outer (but non-global) scope. See PEP 3104 for all the gory details.

scrible
+12  A: 

It's documented in the Language Reference here.

Ned Deily
+2  A: 

A google search for "python nonlocal" turned up the Proposal, PEP 3104, which fully describes the syntax and reasoning behind the statement. in short, it works in exactly the same way as the global statement, except that it is used to refer to variables that are neither global nor local to the function.

Here's a brief example of what you can do with this. The counter generator can be rewritten to use this so that it looks more like the idioms of languages with closures.

def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

Obviously, you could write this as a generator, like:

def counter_generator():
    count = 0
    while True:
        count += 1
        yield count

But while this is perfectly idiomatic python, it seems that the first version would be a bit more obvious for beginners. Properly using generators, by calling the returned function, is a common point of confusion. The first version explicitly returns a function.

TokenMacGuy
I was sure that's what the keyword 'global' does - works up higher enviornments until it reaches a variable with that name. a variable x could be declared at module level, inside a class, then separately in a function inside this class and then in an inner function of that function - how does it know which x to refer to?
ooboo
the thing about global is that it only works for global variables. it cannot see variables in an enclosing, nonglobal scope.
TokenMacGuy
+12  A: 

Compare this, without using nonlocal:

>>> def outer():
       x = 1
       def inner():
           x = 2
           print("inner:", x)
       inner()
       print("outer:", x)


>>> outer()
inner: 2
outer: 1

To this, using nonlocal:

>>> def outer():
       x = 1
       def inner():
           nonlocal x
           x = 2
           print("inner:", x)
       inner()
       print("outer:", x)


>>> outer()
inner: 2
outer: 2
Anon
How is that different than global x?
ooboo
Its very similar - but note that the outer x is not global in the example but is instead defined in the outer function.
Anon
so it lets you do inner classes that reference outer vars, like java?
Dustin Getz
@Dustin - Actually, if you had class A with an attribute x and a subclass B defined in it, you would refer to x from within B as A.x
Anon
(x and B both defined in A)
Anon