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().

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top