Python nonlocal statement
The Python nonlocal statement is similar to the global statement. The global statement allows modification of the global variables inside the local scope. Likewise the nonlocal statement allows modification of any variables that does not belong to the global scopes (say nested scope or enclosing scope) in the local scope.
Link : Python global statement
Think of nonlocal statement as the counterpart of the global statement for non-global variables.
The syntax of using the nonlocal statement is shown below.
nonlocal variable_name
Let us see an example. In the first code we will try to change the value of the nested scope without using the nonlocal statement in the local scope.
>>> def func(): ... ns=111 #nested scope variable ... def foo(): #foo() region begins here ... ns=1200 ... print("Inside foo() ns=",ns) #foo() region ends here ... foo() ... print("Outside foo() ns=",ns) ... >>> func() Inside foo() ns= 1200 Outside foo() ns= 111
We have changed the value of ‘ns’ inside foo(), but it has no effect outside the foo() function.
Note, here the ‘ns=1200’ created inside foo() is a different variable from the ‘ns=111’ defined after the function func() declaration. Since they lie in different code blocks they can have the same name.
Now let us try changing the value of ‘ns’ using the nonlocal statemnt.
>>> def func(): ... ns=111 ... def foo(): ... nonlocal ns ... ns=1200 ... print("Inside foo(), ns=",ns) ... foo() ... print("Outside foo(), ns=",ns) ... >>> func() Inside foo(), ns= 1200 Outside foo(), ns= 1200
Now the value of ‘ns’ both inside and outside the foo() function are the same. And note the ‘ns’ outside the foo() function is same as the ‘ns’ inside the foo().
Some points to note about nonlocal statement
i)The nonlocal statement must always bind to pre-existing variable in the enclosing scope.
We are not allowed to declare a variable with the nonlocal statement unless that variable pre-exist in any enclosing scope.
Consider the code below.
>>> def fuu(): ... n=10 ... def fi(): ... nonlocal h ... print("n=",n)
Try running the code above, you will get the error:
‘File “<stdin>”, line 4
SyntaxError: no binding for nonlocal ‘h’ found‘ .
The ‘h’ variable inside the fi() function does not exist in the enclosing scope, so we are not allowed to declare it as nonlocal, the error makes sense in every ways.
ii)Names declared with nonlocal cannot be same with any of the local variable names
If the local variable has the same name as the enclosing scope variable, we cannot declare the enclosing variable name with the nonlocal statement.
>>> def func(): ... kl=100 ... def gul(): ... kl=199 #local variable ... nonlocal kl ... kl=19191 ... print("Inside gul(), kl=",kl) ... gul()
Running the code above will give the error.
File “<stdin>”, line 5
SyntaxError: name ‘kl’ is assigned to before nonlocal declaration
The variable kl already exit in the local scope, so we cannot declare kl with the nonlocal statement.
Conclusion
If there are many local scopes inside the enclosing scope and each local scope has the nonlocal statement declaration of the same enclosing variable. In such case, the value of the nonlocal declared variable is determined by the function which is called at last.
Consider the code below.
>>> def func(): ... kl=100 ... def foo(): ... nonlocal kl ... kl=111 ... print("Inside foo(), ns=",ns) ... def goo(): ... nonlocal kl ... kl=19000 ... print("Inside goo(), kl=",kl) ... foo() ... goo() ... print('Outside foo() and goo(), kl=',kl) ... >>> func() Inside foo(), ns= 900 Inside goo(), kl= 19000 Outside foo() and goo(), kl= 19000
Since goo() is called after foo(), the value of kl outside foo() and goo() is determined by whatever is assigned to kl inside goo(), which is 19000.
Try calling goo() first and the foo() function second, the ‘kl’ value outside foo() and goo() will be 900.