Python';s闭包-赋值前引用的局部变量

Python';s闭包-赋值前引用的局部变量,python,Python,我试图理解闭包在Python中是如何工作的 我觉得add1在这里应该可以正常工作。我希望在调用helper时定义变量x。但是,它给了我一个赋值前引用的局部变量错误 add2与add1非常相似。它不是给x赋值一个整数,而是给x赋值一个字典。它的行为也符合我的预期x在helper中定义并可引用 import random def add1(): x = 0 def helper(): x = x + 1 return x return hel

我试图理解闭包在Python中是如何工作的

我觉得add1在这里应该可以正常工作。我希望在调用
helper
时定义变量
x
。但是,它给了我一个赋值前引用的
局部变量
错误

add2
add1
非常相似。它不是给x赋值一个整数,而是给x赋值一个字典。它的行为也符合我的预期
x
helper
中定义并可引用

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
的类型不同之外,我还有什么不同之处

您希望编译器知道变量已绑定到闭包之外。这是不正确的,因此您需要使用
非本地
来表示这一点

def add1():
    x = 0
    def helper():
        nonlocal x
        x = x + 1
        return x
    return helper
丹尼斯编辑:


非本地
add2
中不是必需的,因为它只是修改
x
而不是重新绑定它(也就是不重新分配它)。而在
add1
中,
x=x+1
是一个
重新分配

,为什么我不必为
add2
这样做呢?因为你从来没有在
add2()
中重新绑定
x
,你只会对它进行变异。!!!!!!!!!!!!明白了。。。你能在你的回答中加上最后一个细节吗。。。。我想确保其他ppl会看到它。还要注意的是,如果您已将
x+1
分配给一个新引用,如
y
,则不需要
nonlocal
。然后,解释器将在周围范围内查找
x
。当你重新绑定同一个引用时,它会假设你在谈论一个局部变量,并且在局部范围内找不到它。顺便说一句,你返回的是函数引用-两个
helper
都没有被实际调用过。即使改变了这一点,你也不会在后续调用
a2()
时得到额外的键/值对,因为每次都会定义一个新的字典
x
。@TigerhawkT3你能详细说明一下
两个助手都没有被真正调用过吗?如果没有调用它,为什么每次调用
a2
都会向字典中添加新值?哦,我明白了,您正在保存对
add2()
的引用,然后重复调用它;不要介意。