The nonlocal Statement in 3.X

In the prior section we explored the way that nested functions can reference variables in an enclosing function’s scope, even if that function has already returned. It turns out that, in Python 3.X (though not in 2.X), we can also change such enclosing scope variables, as long as we declare them in nonlocal statements. With this statement, nested defs can have both read and write access to names in enclosing functions. This makes nested scope closures more useful, by providing changeable state information.

The nonlocal statement is similar in both form and role to global, covered earlier. Like global, nonlocal declares that a name will be changed in an enclosing scope. Unlike global, though, nonlocal applies to a name in an enclosing function’s scope, not the global module scope outside all defs. Also unlike global, nonlocal names must already exist in the enclosing function’s scope when declared—they can exist only in enclosing functions and cannot be created by a first assignment in a nested def.

In other words, nonlocal both allows assignment to names in enclosing function scopes and limits scope lookups for such names to enclosing defs. The net effect is a more direct and reliable implementation of changeable state information, for contexts that do not desire or need classes with attributes, inheritance, and multiple behaviors.

nonlocal Basics

Python 3.X introduces a new nonlocal statement, which has meaning only inside a function:

def func():
    nonlocal name1, name2, ...            # OK here

>>> nonlocal X
SyntaxError: nonlocal declaration not allowed at module level

This statement allows a nested function to change one or more names defined in a syntactically enclosing function’s scope. In Python 2.X, when one function def is nested in another, the nested function can reference any of the names defined by assignment in the enclosing def’s scope, but it cannot change them. In 3.X, declaring the enclosing scopes’ names in a nonlocal statement enables nested functions to assign and thus change such names as well.

This provides a way for enclosing functions to provide writeable state information, remembered when the nested function is later called. Allowing the state to change makes it more useful to the nested function (imagine a counter in the enclosing scope, for instance). In 2.X, programmers usually achieve similar goals by using classes or other schemes. Because nested functions have become a more common coding pattern for state retention, though, nonlocal makes it more generally applicable.

Besides allowing names in enclosing defs to be changed, the nonlocal statement also forces the issue for references—much like the global statement, nonlocal causes searches for the names listed in the statement to begin in the enclosing defs’ scopes, not in the local scope of the declaring function. That is, nonlocal also means “skip my local scope entirely.”

In fact, the names listed in a nonlocal must have been previously defined in an enclosing def when the nonlocal is reached, or an error is raised. The net effect is much like global: global means the names reside in the enclosing module, and nonlocal means they reside in an enclosing def. nonlocal is even more strict, though—scope search is restricted to only enclosing defs. That is, nonlocal names can appear only in enclosing defs, not in the module’s global scope or built-in scopes outside the defs.

The addition of nonlocal does not alter name reference scope rules in general; they still work as before, per the “LEGB” rule described earlier. The nonlocal statement mostly serves to allow names in enclosing scopes to be changed rather than just referenced. However, both global and nonlocal statements do tighten up and even restrict the lookup rules somewhat, when coded in a function:

  • global makes scope lookup begin in the enclosing module’s scope and allows names there to be assigned. Scope lookup continues on to the built-in scope if the name does not exist in the module, but assignments to global names always create or change them in the module’s scope.

  • nonlocal restricts scope lookup to just enclosing defs, requires that the names already exist there, and allows them to be assigned. Scope lookup does not continue on to the global or built-in scopes.

In Python 2.X, references to enclosing def scope names are allowed, but not assignment. However, you can still use classes with explicit attributes to achieve the same changeable state information effect as nonlocals (and you may be better off doing so in some contexts); globals and function attributes can sometimes accomplish similar goals as well. More on this in a moment; first, let’s turn to some working code to make this more concrete.

nonlocal in Action

On to some examples, all run in 3.X. References to enclosing def scopes work in 3X as they do in 2.X—in the following, tester builds and returns the function nested, to be called later, and the state reference in nested maps the local scope of tester using the normal scope lookup rules:

C:\code> c:\python33\python

>>> def tester(start):
        state = start             # Referencing nonlocals works normally
        def nested(label):
            print(label, state)   # Remembers state in enclosing scope
        return nested

>>> F = tester(0)
>>> F('spam')
spam 0
>>> F('ham')
ham 0

Changing a name in an enclosing def’s scope is not allowed by default, though; this is the normal case in 2.X as well:

>>> def tester(start):
        state = start
        def nested(label):
            print(label, state)
            state += 1            # Cannot change by default (never in 2.X)
        return nested

>>> F = tester(0)
>>> F('spam')
UnboundLocalError: local variable 'state' referenced before assignment

Using nonlocal for changes

Now, under 3.X, if we declare state in the tester scope as nonlocal within nested, we get to change it inside the nested function, too. This works even though tester has returned and exited by the time we call the returned nested function through the name F:

>>> def tester(start):
        state = start             # Each call gets its own state
        def nested(label):
            nonlocal state        # Remembers state in enclosing scope
            print(label, state)
            state += 1            # Allowed to change it if nonlocal
        return nested

>>> F = tester(0)
>>> F('spam')                     # Increments state on each call
spam 0
>>> F('ham')
ham 1
>>> F('eggs')
eggs 2

As usual with enclosing scope references, we can call the tester factory (closure) function multiple times to get multiple copies of its state in memory. The state object in the enclosing scope is essentially attached to the nested function object returned; each call makes a new, distinct state object, such that updating one function’s state won’t impact the other. The following continues the prior listing’s interaction:

>>> G = tester(42)                # Make a new tester that starts at 42
>>> G('spam')
spam 42

>>> G('eggs')                     # My state information updated to 43
eggs 43

>>> F('bacon')                    # But F's is where it left off: at 3
bacon 3                           # Each call has different state information

In this sense, Python’s nonlocals are more functional than function locals typical in some other languages: in a closure function, nonlocals are per-call, multiple copy data.

Boundary cases

Though useful, nonlocals come with some subtleties to be aware of. First, unlike the global statement, nonlocal names really must have previously been assigned in an enclosing def’s scope when a nonlocal is evaluated, or else you’ll get an error—you cannot create them dynamically by assigning them anew in the enclosing scope. In fact, they are checked at function definition time before either an enclosing or nested function is called:

>>> def tester(start):
        def nested(label):
            nonlocal state        # Nonlocals must already exist in enclosing def!
            state = 0
            print(label, state)
        return nested

SyntaxError: no binding for nonlocal 'state' found

>>> def tester(start):
        def nested(label):
            global state          # Globals don't have to exist yet when declared
            state = 0             # This creates the name in the module now
            print(label, state)
        return nested

>>> F = tester(0)
>>> F('abc')
abc 0
>>> state
0

Second, nonlocal restricts the scope lookup to just enclosing defs; nonlocals are not looked up in the enclosing module’s global scope or the built-in scope outside all defs, even if they are already there:

>>> spam = 99
>>> def tester():
        def nested():
            nonlocal spam         # Must be in a def, not the module!
            print('Current=', spam)
            spam += 1
        return nested

SyntaxError: no binding for nonlocal 'spam' found

These restrictions make sense once you realize that Python would not otherwise generally know which enclosing scope to create a brand-new name in. In the prior listing, should spam be assigned in tester, or the module outside? Because this is ambiguous, Python must resolve nonlocals at function creation time, not function call time.