【问题标题】:Difference between closures in python and javascriptpython和javascript中的闭包之间的区别
【发布时间】:2011-05-06 10:37:00
【问题描述】:

在 JS 中,我们可以这样写闭包:

function f(){
var a=0;
function g(){
    alert(a++);
}
return g;
}
g=f()
g()

但是,如果我在 python 中编写以下代码

def f():
    a=0
    def g():
        a+=1
        print a
    return g
g=f()
g()

然后我得到 UnboundedLocalError

谁能告诉我python和JS中闭包的区别?

【问题讨论】:

  • 您真的相信这种差异可以解释您所看到的吗?
  • 我想是的。也欢迎直接解释观察结果

标签: javascript python closures


【解决方案1】:

当您在 Python 中使用 a += 1 时,它指的是 g 函数范围内的本地(未初始化)变量。基本上你可以从上层作用域读取变量,但如果你尝试写它会引用最近作用域中的一个变量。为了让它像你想要的那样工作,你必须使用仅存在 Python 3 的 nonlocal 关键字。据我所知,在 Python 2 中你不能这样做,除非你试图改变的变量是全局的,那么global 关键字就派上用场了。

def f():
    a=0
    def g():
        nonlocal a
        a+=1
        print a
    return g
g=f()
g()

【讨论】:

  • 在 Python 2 中,a = [0]a[0] += 1 使其工作。这是有效的,因为项目分配(以及成员和切片分配)不计为覆盖变量,而是更改对象的状态(在后台,您调用方法)。
  • 看起来像一个丑陋的黑客,但它确实是一个出路。
  • 这与整数是不可变的这一事实有关:a += 1ints 的 a = a + 1 相同。它将名称 a 绑定到一个新表达式,而不是像列表操作那样修改当前由 a 命名的对象。
  • It is 是一个丑陋的黑客,这就是 Python3 毕竟添加非本地的原因。通常最好将代码设计为不需要这种 hack,但有时替代方案的复杂性可能比使用 hacky 方式更有效
【解决方案2】:

python 2 的版本:

def f():
    a=0
    def g():
        g.a+=1
        print g.a

    g.a=a
    return g
g=f()
g()

【讨论】:

  • 这与预期不同:调用 g() 两次返回相同的结果
  • @user607722 修复了问题代码。测试重复调用。虽然为了简化保持状态,但最好将其编码为生成器。
猜你喜欢
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 2022-12-09
  • 2012-05-07
  • 2020-12-24
  • 1970-01-01
  • 2013-01-12
  • 2020-05-27
相关资源
最近更新 更多