Python nonlocal allows us to explicitly choose scope behavior in nested function definitions.
def outer():
x = 1
def inner():
x = 2
print(x)
inner()
print(x)
def outer_nl():
x = 1
def inner():
nonlocal x
x = 2
print(x)
inner()
print(x)
outer() # 2 1
outer_nl() # 2 2
We can achieve the same behavior without nonlocal.
def outer():
context = {}
context['x'] = 1
def inner():
context['x'] = 2
print(context['x'])
inner()
print(context['x'])
Basic lexical vs. dynamic scoping...
MIT Scheme(lexical):
(define (definer)
(define x 1))
(define (printer)
(display x))
(define (letter)
(let ((x 2))
(printer)))
(definer)
(printer) ; error undefined variable
(letter) ; error undefined variable
Common Lisp(dynamic):
(defun definer ()
(defvar x 1))
(defun printer ()
(print x))
(defun letter ()
(let ((x 2))
(printer)))
(definer)
(printer) ; 1
(letter) ; 2