Function attribute used in recursion - does a global function attribute exist?
I have a function:
def fib(n, fib_d = {}):
if n < 2:
return 1
if n not in fib_d:
fib_d[n] = fib(n-2) + fib(n-1)
return fib_d[n]
fib(1000)
# a big number returned in an instance
Then I try to create fib_d
as an attribute of a function which data I could access:
def fib(n):
fib.fib_d = {}
if n < 2:
return 1
if n not in fib.fib_d:
fib.fib_d[n] = fib(n-2) + fib(n-1)
return fib.fib_d[n]
fib(10)
# returns 89 in an instance
fib(100)
# runs till I stop it
So I am guessing that fib_d
is being created each time as an empty parameter, hence the slow calculation
I am wondering if I can have a global
function attribute so that I could access it's content like:
fib.fib_d
# {2: 2, 3: 3, 4: 5, 5: 8, 6: 13, 7: 21, 8: 34, 9: 55, 10: 89, ..., n: m}
I tried:
def fib(n, fib.fib_d):
...
But that's not valid, I understand that probably functions attribute should be bound only to that function but I am curious if there is such thing as global function attributes or at least attribute that can be used in a recursion.
I would just use a cache, or lru_cache.
But to do it like you've asked for, the easiest way to do this is to define your function within a closure:
def make_fib():
def fib(n):
if n < 2:
return 1
if n not in fib.fib_d:
fib.fib_d[n] = fib(n-2) + fib(n-1)
return fib.fib_d[n]
fib.fib_d = {}
return fib
f= make_fib()
f(2000)
That way, we have an attribute of the function properly scoped.
it seems you just want to cache the results for each func
from functools import cache
@cache
def fib(n):
if n < 2:
return 1
return fib(n-2) + fib(n-1)
You can use getattr
to fetch the attribute if it already exists or create it otherwise:
def fib(n):
if n < 2:
return 1
fib.cache = getattr(fib, 'cache', {})
if n not in fib.cache:
fib.cache[n] = fib(n-2) + fib(n-1)
return fib.cache[n]
This is essentially just altering your unconditional creation of fib_d
to only happen if it doesn't already exist; it's self-contained within the function and doesn't need an external definition or closure for the attribute.
You can check if the function already has an attribute fib_d
:
def fib(n):
if n < 2:
return 1
if not hasattr(fib, "fib_d"):
fib.fib_d = {}
if n not in fib.fib_d:
fib.fib_d[n] = fib(n - 2) + fib(n - 1)
return fib_d[n]
fib(1000)