Python - locals() and closure
Question
I can not find an adequate explanation for this behavior.
>>> def a():
... foo = 0
... print locals()
... def b():
... print locals()
... b()
>>> a()
{'foo': 0}
{}
But:
>>> def a():
... foo = 0
... print locals()
... def b():
foo
... print locals()
... b()
>>> a()
{'foo': 0}
{'foo': 0}
I understand that in the second case there is a closure, but I can not find a detailed description of what actually is and under what conditions should return the function locals()
.
Solution
locals() built-in function prints local symbol table which is bound to a code object, and filled up when interpreter receives a name in a source code.
Second example, when disassembled, will contain LOAD_GLOBAL foo bytecode instruction in b function code. This LOAD_GLOBAL instruction will move up the scope, find outer foo name and bind it to the code object by adding name offset into co_names attribute of the closure's (function b) code object.
locals() function prints local symbol table (as was said before, co_names attribute of function's code object).
Read more about code objects here.
OTHER TIPS
If you don't assign to foo
within the closure, Python resolves it to the foo
of the scope one level up (and on up until it finds a foo
somewhere or throws an exception).
By mentioning foo
within b()
in the second example, you put foo
into the locals within b()
, but it resolves to the foo
within the body of a()
. If you assign, say, foo = 1
in b()
, you would see
{'foo': 0}
{'foo': 1}
as the output.