Closures In Python
Solution 1:
The problem is in your scoping, not in your closures. If you're up for some heavy reading, then you can try http://www.python.org/dev/peps/pep-3104/.
If that's not the case, here's the simple explanation:
The problem is in the statement global get
. global
refers to the outermost scope, and since there isn't any global function get
, it throws.
What you need, is an access specifier for variables in the enclosing scope, and not the global scope.
In python 3.0, as I've tested, the nonlocal
keyword is exactly what you need, in the place of global
.
nonlocal get
...
In python 2.x, I just removed the global get
and the oldget
references and it works properly.
Solution 2:
You want to put global get
at the beginning of every function (except get
itself).
the def get
is an assignment to the name get
, so you want get to be declared global before that.
Putting global get
in mfun and vset makes them work. I can't point to the scoping rules that makes this necessary, but it works ;-)
Your conses are quite lispy too... :)
Solution 3:
Get
is not global, but local to the surrounding function, that's why the global
declaration fails.
If you remove the global
, it still fails, because you can't assign to the captured variable name. To work around that, you can use an object as the variable captured by your closures and than just change properties of that object:
classMemo(object):
pass
def memoize(fn):
def defaultget(key):
return (False,)
memo = Memo()
memo.get = defaultget
def vset(key, value):
oldget = memo.get
def newget(ky):
if key==ky: return (True, value)
return oldget(ky)
memo.get = newget
def mfun(*args):
cache = memo.get(args)
if cache[0]: return cache[1]
val = apply(fn, args)
vset(args, val)
returnvalreturn mfun
This way you don't need to assign to the captured variable names but still get what you wanted.
Solution 4:
Probably because you want the global get while it isn't a global? By the way, apply is deprecated, use fn(*args) instead.
def memoize(fn):
def get(key):
return (False,)
def vset(key, value):
def newget(ky):
if key==ky: return (True, value)
returnget(ky)
get = newget
def mfun(*args):
cache = get(args)
if (cache[0]): return cache[1]
val = fn(*args)
vset(args, val)
returnvalreturn mfun
def fib(x):
if x<2: return x
return fib(x-1)+fib(x-2)
def fibm(x):
if x<2: return x
return fibm(x-1)+fibm(x-2)
fibm = memoize(fibm)
Solution 5:
I think the best way would be:
classMemoized(object):
def__init__(self,func):
self.cache = {}
self.func = func
def__call__(self,*args):
if args in self.cache: return cache[args]
else:
self.cache[args] = self.func(*args)
return self.cache[args]
Post a Comment for "Closures In Python"