Python的关闭 - 在赋值之前引用的局部变量

问题描述:

我想了解在Python中闭包的工作原理。Python的关闭 - 在赋值之前引用的局部变量

我觉得像add1应该在这里工作得很好。我期望在调用helper时定义变量x。但是,它给我一个Local variable referenced before assignment错误。

add2add1非常相似。它不是用一个整数赋值x,而是用一个字典赋值。它的行为也与我期望的一致。 xhelper内定义和引用。

import random 

def add1(): 
    x = 0 
    def helper(): 
     x = x + 1 
     return x 
    return helper 

def add2(): 
    x = {} 
    def helper(): 
     x[random.randint(1,1000)] = 3 
     return x 
    return helper 

if __name__ == '__main__': 
    a1 = add1() 
    a2 = add2() 

    # print(a1()) #This causes error 
    print(a2()) #{650: 3} 
    print(a2()) #{650: 3, 333: 3} 

这是什么逻辑?除了x的类型不同之外,我还有什么不同?

+0

顺便说一下,您正在返回函数引用 - 实际上并没有调用“helper”。 – TigerhawkT3

+0

甚至改变这种情况,在后续调用'a2()'时不会获得额外的键/值对,因为每次都定义一个新的字典'x'。 – TigerhawkT3

+0

@ TigerhawkT3你能否更详细地说明“这两个助手都没有真的叫过”?如果没有被调用,为什么调用'a2'每次都会为字典添加新的值? – denniss

您期待编译器知道该变量已被绑定在闭包之外。这是不正确的,因此您需要使用nonlocal来表明这一点。

def add1(): 
    x = 0 
    def helper(): 
     nonlocal x 
     x = x + 1 
     return x 
    return helper 

编辑由丹尼斯:

nonlocaladd2必要的,因为它只是修改x,而不是再结合它(又名不是重新分配它)。而在add1,x= x+1re-assignment

+0

以及我怎么没有为'add2'做这个? – denniss

+0

因为你永远不会在'add2()'中重新绑定'x',所以你只能改变它。 –

+1

!!!!!!!!!!!! GOTCHA ...请问您能否将最后的细节添加到您的答案中....我想确保其他人会看到它。 – denniss