While exploring some solutions to my previous question about the inner workings of Python scope, I learned about the
__closure__ attribute. It seems that Python uses this attribute to access variables defined in an outer scope from within a nested function.
We can see this in action by doing the following:
x = 5
print(*(cell.cell_contents for cell in bar.__closure__))
This shows two enclosed values,
5 and the function
What I don't understand is how this works - since, the
__closure__ attribute merely contains a tuple of cells which store the enclosed values. But there's no information about the enclosed variables names - (i.e. the cells are stored in a
tuple, not a
dict). So how does Python know the names of the variables which have been enclosed?
The python compiled code uses indices; the variables are tied to an index into the cells structure.
>>> def foo(): ... x = 5 ... def bar(): ... return x ... return bar ... >>> bar = foo() >>> import dis >>> dis.dis(bar) 4 0 LOAD_DEREF 0 (x) 3 RETURN_VALUE
LOAD_DEREF bytecode refences the first cell value.