I'm trying to learn about dynamic programming. I've gone through an example of how to find the Fibonacci number of an inputn
, while caching the result of each "new" call as I go.
I understand the order in which the function recursively calls: fib(5) -> fib(4) -> fib(3) -> fib(2) -> fib(1) -> fib(0) -> fib(1) -> fib(2) "Cache found" -> fib(3) "Cache found" for n = 5
I'm struggling to understand how the final fib(2) and fib(3) calls have access to the updated cache, as each call only returns an integer, not the list, and I don't think I have the list declared as a global variable.
I originally expected the list to behave like the integer x in my code, so would welcome explanations for how the values have been passed back up.
Code:
def fib(n, cache, x):
print(n, cache)
print("x: ", x)
x += 1
if n == 0 or n == 1:
return n
if cache[n] == 0:
cache[n] = fib(n-1, cache, x) + fib(n-2, cache, x)
else:
print("Cache called on", n)
return cache[n]
def main():
n = 5
x = 0
cache = [0 for _ in range(n+1)]
print(fib(n, cache, x))
print(cache)
print("x: ", x)
if __name__ == "__main__":
main()
Output:
5 [0, 0, 0, 0, 0, 0]
x: 0
4 [0, 0, 0, 0, 0, 0]
x: 1
3 [0, 0, 0, 0, 0, 0]
x: 2
2 [0, 0, 0, 0, 0, 0]
x: 3
1 [0, 0, 0, 0, 0, 0]
x: 4
0 [0, 0, 0, 0, 0, 0]
x: 4
1 [0, 0, 1, 0, 0, 0]
x: 3
2 [0, 0, 1, 2, 0, 0]
x: 2
Cache called on 2
3 [0, 0, 1, 2, 3, 0]
x: 1
Cache called on 3
5
[0, 0, 1, 2, 3, 5]
x: 0