3 minute read

23.12.13 Reference Modified

23.12.24 Why nonlocal syntax error
With global declaration, names in global scope are not only referenced but also assigned. I learned how to reference in the enclosing function scope, but I have not yet introduced how to do assignment.

Nonlocal

Starting with python 3.X version, you can use a namespace declartion called nonlocal . This declartion statement is very similar to a global declartion. Now, let’s find out about this.

Assignment

X = 88

def C() :
    global X
    X = 999

    print(X)
C()
print(X)

If you use the global statement, assignment to the global scope is possible.

def tester(start) :
    state = start
    def nested(label) :
        nonlocal state
        print(label, state)
        state +=1
        
    return nested

F = tester(0)

F('spam')

F('ham'

If you use a nonlocal statement, you can also assign an assignment to a name in the enclosing func scope.

Skip search scope

The global statement starts searching whether the name exists in the scope from the enclosing module scope. After the global scope, the built-in scope is searched, and if name does not exist in the scope, the name is created in the global scope. And then, assignment is done.

Nonlocal statements similarly start looking up names in the enclosing func scope. However, unlike global, if name does not exist in the enclosing func scope, a syntax error occurs.

scope limits

The global statement can be used in any scope. However, nonlocal statements can only be used in enclosing function scope.

pre-assigned

As mentioned above, the global statement creates a name if the name does not exist in the scope. However, for nonlocal statements, if name does not exist in the enclosing scope, a syntax error occurs. In other words, if there is no name in the enclosing scope, a new name cannot be created, so the name must exist. This is an unavoidable design because of the difference by the priority of the serach scope. To search for a name in Python, name resolution is performed in LEGB order. If assigned to nonlocal, it is impossible to know which scope belongs to either the Enclosing func scope or the Global scope by name alone. Therefore, assign is not allowed in nonlocal.

Why nonlocal sytax error

Why Syntax Error?

A question may arise as to why not it would be possible to create a name in the frame of the parent function and assign the nonlocal statement like a global statement. In response to this, I will attach an explanation from Guido van Rossum, the founder of Python.

   def outer():
     def inner1(x):
       global a
       a = x
     def inner2():
       return a
     return inner1, inner2
   f1, f2 = outer()
   g1, g2 = outer()
   f1(42)
   g1(0)
   print(f2())

In the Python example above, f2() prints 0. In the process of calling f1(42), a was created in the global frame, and the last time it was assigned was when calling g1(0). Therefore, 0 is ultimately assigned to a and 0 is output.

How should it have worked if it had been nonlocal instead of global? Regarding this, we consider two solutions.

  1. Generates Syntax Error. (not Compile Error)
  2. Select an appropriate scope and create a name.

If you select 2, you can operate as follows. If there is one outer scope, just create a name in the global frame. If there are multiple outer scopes, you can create a name in the innermost scope among the outer scopes.

but if there is no outer scope, the method of creating a name in the outer scope cannot be applied. Exceptions have to be made, which is not natural.

Therefore, Guido van Rossum argued that syntax errors should be generated, and modified python to generate syntax errors.

lifecycle

When using the global statement, the name is bound to the global scope, so the name (variable) is alive and can be accessed until it leaves the global scope. However, the name assigned by the nonlocal statement is in the enclosing scope, so if it goes out of that scope, the name will expire. (Of course, you can bind the name to the enclosing block using the closure function.)

Advantages of Nonlocal

So, why use Nonlocal statement? The significance of the nonlocal statement is that it keeps a copy of the mutable state in memory. Therefore, it can be considered effective in the following situations.

  • When global variable cannot be used
  • When using a class is an overkilled solution

Reference

PEP 3104 – Access to Names in Outer Scopes Python.org

Learning python chp17 Scope : Learning Python chp 17

4.2.2. Resolution of names

9.2. Python Scopes and namespace

7.12. global statement 7.13. nonlocal statement

Nonlocal Syntax Error reason

Leave a comment