How Python binds names, builds frames, and creates closures
function values, passed as arguments, returned as resultsx = 2
y = x + 1
print(y)
x -> 2, y -> 3x = 2
# inside a function: x = 99
def square(x):
return x * x
print(square(3))
print(square(square(3)))
x -> 3 (then another call with x -> 9)square was defined (global here)x = 1
def f(x):
return x + 1
def g():
return x + 1
print(f(10))
print(g())
x hides global x inside fg finds x by walking to globaldef make_adder(n):
def adder(x):
return x + n
return adder
add_three = make_adder(3)
print(add_three(4))
adder carries a pointer to the frame where n -> 3add_three(4): local x -> 4, then lookup finds n in parentlambda creates the same kind of function objectf = lambda x: x + 1
print(f(5))
print((lambda x: x * x)(5))
lambda vs def: same closure idea, different syntaxlambda was evaluateddef make_counter():
n = 0
def inc():
nonlocal n
n += 1
return n
def get():
return n
return inc, get
inc, get = make_counter()
print(inc())
print(inc())
print(get())
inc and get close over the same nnonlocal updates an existing binding (mutation topic later)def make_adder(n):
def adder(x):
return x + n
return adder
add_three = make_adder(3)
# Predict before running:
# What will this print?
n = 100
print(add_three(10))
n does not matter here
Powered by SciMigo AI Tutor - https://scimigo.com