Question
Is there any way to modify the bound value of one of the variables inside a closure?
TLDR
Yes, this is possible starting in Python 3.7.0 alpha 1:
localClosure.__closure__[0].cell_contents = 0
Details
In Python, a closure remembers the variables from the scope in which it was defined by using a special __closure__
attribute. The __closure__
attribute is a tuple of cell
objects representing the variables from the outer scope, and the values of those variables are stored in the cell_contents
attribute of each cell
.
Given the code from the question, this can be seen by running the following:
# print the list of cells
print(localClosure.__closure__)
# (<cell at 0x7f941ca27a00: int object at 0x7f941a621950>, <cell at 0x7f941ca27eb0: int object at 0x7f941a621970>)
# print the values in the cells
print(', '.join(str(cell.cell_contents) for cell in localClosure.__closure__))
# 2, 3
# print the value in the first cell (var_a)
print(localClosure.__closure__[0].cell_contents)
# 2
The cell_contents
attribute of the cell
objects first became writable with bpo-30486 which was first included in Python 3.7.0 alpha 1
Complete working example:
def foo():
var_a = 2
var_b = 3
def _closure(x):
return var_a + var_b + x
return _closure
localClosure = foo()
# Local closure is now "return 2 + 3 + x"
a = localClosure(1) # 2 + 3 + 1 == 6
# DO SOME MAGIC HERE TO TURN "var_a" of the closure into 0
# ...but what magic? Is this even possible?
# the magic
# this changes the value in the cell representing var_a to be 0
localClosure.__closure__[0].cell_contents = 0
# Local closure is now "return 0 + 3 + x"
b = localClosure(1) # 0 + 3 + 1 == 4