PEP 3104 - Access to Names in Outer Scopes. The specification for the nonlocal statement.
https://realpython.com/python-namespaces-scope/
Namespaces and Scope in Python
A 'scope' defines the visibility of a name/variable within a block.
A 'namespace' is a collection of currently defined symbolic names along with information about the object that each name references. You can think of a namespace as a dictionary in which the keys are the object names and the values are the objects themselves.
There are four types of namespaces in a Python program (LEGB rule):
(1) Local
(2) Enclosing
(3) Global
(4) Builtin
def my_len(sequence): # sequence is local
"""Return the length of a sequence."""
length = 0 # length is local
for item in sequence: # item is local
length += 1
return length
X = 99 # global name
def func(): # local namespace
#print(X) # UnboundLocalError, X will be local
X = 88 # local name
print(X) # 88, reference to the local X
func() # 88
print(X) # 99, X is global here
X = 99 # global name
def func():
global Z # global statement (declaration)
print(X) # reading global name
Y = 88 # local name
Z = 77 # Z is created
#print(Z) # NameError, Z is not defined
X = 55 # global X changed
func() # 55, here the function body is executed
#print(Y) # NameError, Y is not defined
print(Z) # 77, Z is global
X = 99 # global name
def func():
global X # global statement
print(X) # OK
X = 88 # global X changed
func() # 99
print(X) # 88
# PEP 227 - Statically Nested Scopes
x = 1
def outer():
#from math import * # SyntaxError: import * is not allowed ...
import math # possible
x = 2
def inner(): # nested scope
print(x)
inner()
outer() # print 2 from nested scope, not 1 from global scope
#print(math.sin(1)) # NameError: name 'math' is not defined
def make_score(score=0):
for i in [1, 2, 3, 4]:
def increment(step=i):
#global score
#NameError: name 'score' is not defined
nonlocal score # if not, there is an exception (Py3)
#UnboundLocalError: local variable 'score' referenced before assignment
# 'score' is not local and it is not global
score = score + step
print(score)
increment()
make_score() # 1 3 6 10