Python中的闭包 [英] Closures in Python
问题描述
我一直在努力学习Python,虽然我热衷于在Python中使用闭包,但是我一直无法让一些代码正常工作:
def memoize(fn):
def get(key):
return(False,)
def vset ):
global get
oldget = get
def newget(ky):
if key == ky:return(True,value)
return oldget
get = newget
def mfun(* args):
cache = get(args)
if(cache [0]):return cache [1]
val = apply(fn,args)
vset(args,val)
return val
return mfun
def fib(x):
if x <2:return x
return fib(x-1)+ fib(x-2)
def fibm $ b if x< 2:return x
return fibm(x-1)+ fibm(x-2)
fibm = memoize(fibm)
基本上,这应该是使用闭包来保持函数的memoized状态。我意识到,可能有更快,更容易阅读,一般更多的Pythonic的方式来实现这一点;然而,我的目标是明确地了解闭包在Python中如何工作,以及它们如何与Lisp不同,所以我对替代解决方案不感兴趣,只是为什么我的代码不工作,我可以做什么(如果有什么)修复
我遇到的问题是当我尝试使用 fibm
- Python坚持认为 get
未定义:
Python 2.6.1(r261:67515, darwin
输入帮助,版权,信用或许可证更多信息。
>>>> import memoize
>>>> memoize.fibm(35)
回溯(最近一次调用):
在< module>中的文件< stdin&
文件memoize.py,第14行,在mfun
cache = get(args)
NameError:全局名'get'未定义
>>
看到我是Python的新手,我不知道我是否做错了,或者这只是语言的限制。我希望它是前者。 : - )
问题在于你的范围,而不是你的闭包。如果您想阅读一些重要内容,可以尝试 http:// www .python.org / dev / peps / pep-3104 / 。
如果不是这样,下面是简单的解释:
问题出在语句 global get
中。 全局
是指最外层的范围,因为没有任何全局函数 get
,它会抛出。 >
你需要的是一个访问说明符,用于包含范围中的变量,而不是全局范围。
在python 3.0,正如我测试的,非本地
关键字正是你需要的,在全局
的位置。 / p>
非本地获取
...
在python 2.x中,我删除了全局get
和 oldget
引用,它可以正常工作。
I've been trying to learn Python, and while I'm enthusiastic about using closures in Python, I've been having trouble getting some code to work properly:
def memoize(fn):
def get(key):
return (False,)
def vset(key, value):
global get
oldget = get
def newget(ky):
if key==ky: return (True, value)
return oldget(ky)
get = newget
def mfun(*args):
cache = get(args)
if (cache[0]): return cache[1]
val = apply(fn, args)
vset(args, val)
return val
return 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)
Basically, what this is supposed to do is use closures to maintain the memoized state of the function. I realize there are probably many faster, easier to read, and in general more 'Pythonic' ways to implement this; however, my goal is to understand exactly how closures work in Python, and how they differ from Lisp, so I'm not interested in alternative solutions, just why my code doesn't work and what I can do (if anything) to fix it.
The problem I'm running into is when I try to use fibm
- Python insists that get
isn't defined:
Python 2.6.1 (r261:67515, Feb 1 2009, 11:39:55)
[GCC 4.0.1 (Apple Inc. build 5488)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import memoize
>>> memoize.fibm(35)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "memoize.py", line 14, in mfun
cache = get(args)
NameError: global name 'get' is not defined
>>>
Seeing as I'm new to Python, I don't know if I've done something wrong, or if this is just a limitation of the language. I'm hoping it's the former. :-)
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.
这篇关于Python中的闭包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!