When using the functools caching functions like lru_cache, the inner function doesn't update the values of the non local variables. The same method works without the decorator.
Are the non-local variables not updated when using the caching decorator? Also, what to do if I have to update non-local variables but also store results to avoid duplicate work? Or do I need to return an answer from the cached function necessarily?
Eg. the following does not correctly update the value of the nonlocal variable
def foo(x):
outer_var=0
@lru_cache
def bar(i):
nonlocal outer_var
if condition:
outer_var+=1
else:
bar(i+1)
bar(x)
return outer_var
Background
I was trying the Decode Ways problem which is finding the number of ways a string of numbers can be interpreted as letters. I start from the first letter and take one or two steps and check if they're valid. On reaching the end of the string, I update a non local variable which stores the number of ways possible. This method is giving correct answer without using lru_cache but fails when caching is used. Another method where I return the value is working but I wanted to check how to update non-local variables while using memoization decorators.
My code with the error:
ways=0
@lru_cache(None) # works well without this
def recurse(i):
nonlocal ways
if i==len(s):
ways+=1
elif i<len(s):
if 1<=int(s[i])<=9:
recurse(i+1)
if i+2<=len(s) and 10<=int(s[i:i+2])<=26:
recurse(i+2)
return
recurse(0)
return ways
The accepted solution:
@lru_cache(None)
def recurse(i):
if i==len(s):
return 1
elif i<len(s):
ans=0
if 1<=int(s[i])<=9:
ans+= recurse(i+1)
if i+2<=len(s) and 10<=int(s[i:i+2])<=26:
ans+= recurse(i+2)
return ans
return recurse(0)