First of all, this post does NOT answer my question or give me any guide to answer my question at all.
My question is about mechanism function resolving non-local variables.
Code
# code block 1
def func():
vals = [0, 0, 0]
other_vals = [7, 8, 9]
other = 12
def func1():
vals[1] += 1
print(vals)
def func2():
vals[2] += 2
print vals
return (func1, func2)
f1, f2 = func()
Try to run f1, f2:
>>> f1()
[0, 1, 0]
>>> f2
[0, 1, 2]
This shows that the object previously referred by vals are shared by f1 and f2, and not garbage collected after execution of func.
Will objects referred by other_vals and other be garbage collected? I think so. But how does Python decide not to garbage collect vals?
Assumption 1
Python interpreter will resolve variable names within func1 and func2 to figure out references inside the function, and increase the reference count of [0, 0, 0] by 1 preventing it from garbage collection after the func call.
But if I do
# code block 2
def outerfunc():
def innerfunc():
print(non_existent_variable)
f = outerfunc()
No error reported. Further more
# code block 3
def my_func():
print(yet_to_define)
yet_to_define = "hello"
works.
Assumption 2
Variable names are resolved dynamically at run time. This makes observations in code block 2 and 3 easy to explain, but how did the interpreter know it need to increase reference count of [0, 0, 0] in code block 1?
Which assumption is correct?
valsin the returned function objectsfunc1andfunc2, and that ref preventsvalsfrom being garbage collected. See What exactly is contained within a obj.__closure__?. In your 2nd examplenon_existent_variableis presumably a global, and you will get an error if you don't define it before callingf.