Nonlocal in Action

On to some examples, all run in 3.0. References to enclosing def scopes work as they do in 2.6. 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:\\misc>c:\python30\python >>> def tester(start):

... state = start # Referencing nonlocals works normally

... print(label, state) # Remembers state in enclosing scope

... return nested

spam 0

ham 0

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

... state += 1 # Cannot change by default (or in 2.6)

... return nested

UnboundLocalError: local variable 'state' referenced before assignment

Using nonlocal for changes

Now, under 3.0, 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 ... def nested(label): ... nonlocal state

... return nested

spam 0

ham 1

eggs 2

As usual with enclosing scope references, we can call the tester factory 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

# Each call gets its own state

# Remembers state in enclosing scope

# Allowed to change it if nonlocal

# Increments state on each call 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

Boundary cases

There are a few things to watch out for. 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:

... nonlocal state # Nonlocals must already exist in enclosing def!

... return nested

SyntaxError: no binding for nonlocal 'state' found

... global state # Globals don't have to exist yet when declared

... state = 0 # This creates the name in the module now

... return nested

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!

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

0 0

Post a comment