I'm learning about optimization in Composing Programs. I have 3 functions. memo
is for memoization technique, count
is a wrapper, so every time fib
is called a counter is activated. fib
is just an implementation of Fibonacci with recursivity.
def memo(f):
cache = {}
def memoized(n):
if n not in cache:
cache[n] = f(n)
return cache[n]
return memoized
def count(f):
def counted(*args):
counted.call_count += 1
return f(*args)
counted.call_count = 0
return counted
def fib(n):
if n == 0:
return 0
if n == 1:
return 1
return fib(n - 2) + fib(n - 1)
To call the functions, I assing count(fib)
to counted_fib
, so every call is recorded. And* fib
*variable is reasigned (now, fib
is memo(counted_fib)
not the original function)
counted_fib = count(fib)
fib = memo(counted_fib)
My problem start when the function fib
is called (e.g. fib(19)
) Everything works as it should be, but the recursion inside the original function (return fib(n - 2) + fib(n - 1)
) trigger fib
as memo(counted_fib)
.
This is not a problem about something that is not working. I'm just trying to understand why it happens if one thing is declared before another.
If what you are confused about is the way that the fib
name behaves when being reassigned from the original fib()
function to being a variable calling memo(counted_fib
, I think this article about python's namespace behavior will help.
Python programs are executed starting from the first statement. But even before that, the global namespace is loaded. So you assign the fib name to fib()
. But later on, you change that assignment to memo(counted_fib)
, and that last assignment is the one loaded with the global namespace once the program starts.
Hope it helps!