Python中的闭包 [英] Closures in Python

查看:297
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆