rahmu wroteThe cache variable lingers on because of the creation of the closure. And to the best of my knowledge (and that of the guy who very nicely answered my question) there's no way of accessing the variable from outside the _decoed function.
Today I found a way to access these variables in Python. Each function object has a
__closure__ attribute that holds the variables.
The variable __closure__ is a tuple of
cell objects.
Case study
Let's consider the code at hand:
def cached(f):
cache = {}
def _decoed(*args):
if args in cache:
return cache[args]
else:
cache[args] = f(*args)
return cache[args]
return _decoed
@cached
def fib(n):
if n <= 1:
return n
else:
return fib(n-1)+fib(n-2)
Let's read inside the closure
We can access the cache directory of the function like this:
>>> fib.__closure__
(<cell at 0x14b5210: dict object at 0x14ad7e0>, <cell at 0x14b5328: function object at 0x7fbc9fa9f628>)
As you can see, the cell 0 holds a dict object. We can inspect the variable it contains using the attribute
cell_contents:
>>> fib.__closure__[0].cell_contents
{}
Of course the dict is still empty. If we call fib(5) we expect to find 6 values inserted:
>>> fib(5)
5
>>> fib.__closure__[0].cell_contents
{(0,): 4, (1,): 1, (2,): 1, (3,): 2, (4,): 3, (5,): 5}
Let's write inside the closure
This one scares me a bit. You can write and modify the values inside the cells.
EDIT: Turns out you can modify the values inside the dict, because dicts are mutable. But you cannot change the content of a cell.
Like this:
>>> fib.__closure__[0].cell_contents[(5,)] = -3 # modifying the value inside the cache dict
>>> fib(5)
-3
>>> fib(6)
0