Show global in a function and nonlocal in a nested function, and explain what each one rebinds.
Both global and nonlocal tell Python that a name inside a function refers to a binding that lives further out. The difference is how far out they reach.
counter = 0
def bump():
global counter # this name lives at module level
counter += 1
bump()
bump()
print(counter) # 2
def outer():
total = 0
def inner():
nonlocal total # this name lives in outer()'s scope
total += 10
return total
inner()
return total
print(outer()) # 10The global keyword reaches the module scope, which is the outermost namespace in the program. The bump function can read and rebind the module-level counter, and the change is visible to everybody else in the file.
The nonlocal keyword reaches the nearest enclosing function scope and it skips the module entirely. Inside outer, the name total is a local of outer, so inner can read and rebind it with nonlocal, and outer sees the new value of 10 afterwards. Without the nonlocal statement, the line total += 10 inside inner would create a brand new local named total inside inner, and outer would still see 0 when it returns.
Two rules catch people out here. nonlocal needs the name to already exist in an enclosing function scope. There is no such thing as a nonlocal that creates a module-level name, and using nonlocal for a name that does not exist yet raises a SyntaxError before your program even starts. And nonlocal can only skip function scopes. It cannot reach a name in a class body, because class bodies are not part of the chain of enclosing scopes that nonlocal searches.
The safe pattern is the same one that you use for global. Rebind a name rather than mutating it wherever you can, and prefer returning a value over changing one in place.