简体   繁体   English

Python闭包

[英]Python closures

def counter(x):

    def _cnt():
        #nonlocal x
        x = x+1
        print(x)
        return x

    return _cnt
a = counter(0)
print(a())

Above code gives the following error 上面的代码给出了以下错误

UnboundLocalError: local variable 'x' referenced before assignment UnboundLocalError:赋值前引用的局部变量'x'

Why this is not able to create a new object with value 'x+1' in the namespace of _cnt and bind it to x. 为什么这不能在_cnt的命名空间中创建值为'x + 1'的新对象并将其绑定到x。 we will have reference x in both function namespaces 我们将在两个函数名称空间中引用x

As soon as you assign to a name in a given scope, all references to the same name inside the same scope are local. 只要分配给定范围内的名称,同一范围内对同一名称的所有引用都是本地的。 Hence x + 1 cannot be evaluated (as it tries to reference the local x ). 因此,无法评估x + 1 (因为它试图引用本地x )。

Hence this works: 因此这有效:

def f():
    x = 42
    def g():
        print(x)
    g()
f()

But this doesn't: 但这不是:

def f():
    x = 42
    def g():
        print(x)
        x = 42
    g()
f()

The first print has this bytecode: 第一个print有这个字节码:

0 LOAD_GLOBAL              0 (print) 
3 LOAD_DEREF               0 (x) 
6 CALL_FUNCTION            1 
9 POP_TOP  

while the second print has this one: 而第二个print有这个:

0 LOAD_GLOBAL              0 (print) 
3 LOAD_FAST                0 (x) 
6 CALL_FUNCTION            1 
9 POP_TOP 

The scopes of function counter and _cnt are not the same. 函数counter_cnt的范围不一样。 Even though they're nested, it doesn't matter. 即使它们是嵌套的,也没关系。

So the x in counter does not exist in _cnt . 所以_cnt中不存在counter中的x Perhaps pass it as an argument (or use nonlocal , as you seemed to have understood) 也许把它作为一个论点传递(或者使用nonlocal ,正如你似乎已经理解的那样)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM