Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python闭包/嵌套函数在分配给外部数组时失败_Python_Closures - Fatal编程技术网

python闭包/嵌套函数在分配给外部数组时失败

python闭包/嵌套函数在分配给外部数组时失败,python,closures,Python,Closures,如果符号 被引用的文件被分配: def outer(): p = [] def gen(): def touch(e): if e[0] == 'add': p.append(e); elif e[0] == 'rem': p = [ x for x in p if not (x[1] == e[1]) ] return touch

如果符号 被引用的文件被分配:

def outer():
    p = []
    def gen():
        def touch(e):
            if e[0] == 'add':
                p.append(e);
            elif e[0] == 'rem':
                p = [ x for x in p if not (x[1] == e[1]) ]
        return touch
    f = gen()
    for i in [["add","test1"],["add","test2"],["rem","test2"],["rem","test1"]]:
        f(i)      

outer();
结果是:

Traceback (most recent call last):
  File "b.py", line 22, in <module>
    outer();
  File "b.py", line 20, in outer
    f(i)      
  File "b.py", line 14, in touch
    p.append(e);
UnboundLocalError: local variable 'p' referenced before assignment
错误消失了,但是代码不是我想要的。python闭包/嵌套函数是否会出现上述行为?我是否需要将数组包装在对象内部进行修改,然后只调用函数

另一方面,这一点很有效:

class o():
    def __init__(self):
        self.p = []
    def add(self,e):
        self.p.append(e);
    def rem(self,e):
        self.p = [ x for x in self.p if not (x[1] == e[1]) ]

def outer():
    p = o()
    def gen():
        def touch(e):
            if e[0] == 'add':
                p.add(e);
            elif e[0] == 'rem':
                p.rem(e)
        return touch
    f = gen()
    for i in [["add","test1"],["add","test2"],["rem","test2"],["rem","test1"]]:
        f(i)      

outer();

由于您在
touch
内部分配
p
,因此它在
touch
中成为一个局部变量,并在封闭范围内有效地“隐藏”所有其他名称
p
。为了告诉Python您实际上想要引用
outer
中的
p
,您应该使用
非本地p
,例如:

def outer():
    p = []
    def touch(e):
        # The following line is required to refer to outer's p
        nonlocal p
        if e[0] == 'add':
            p.append(e)
        elif e[0] == 'rem':
            p = [ x for x in p if not (x[1] == e[1]) ]
    for i in [["add","test1"],["add","test2"],["rem","test2"],["rem","test1"]]:
        touch(i)
outer()
第二个示例之所以有效,是因为在
touch
的两种情况下都引用了
p
属性,而不是赋值(
p=…


参见参考文档,其中提出了
非本地
语法
非本地
仅存在于Python 3中,但如果有必要使用Python 2。

如果您在touch函数中定义p而不是闭包,它似乎可以正常工作。或者你可以定义
def touch(e,p):
并使用
touch(i,p)
@Alexander:你说得对,我更改了标题/示例相当令人讨厌的陷阱。谢谢你的提示。
def outer():
    p = []
    def touch(e):
        # The following line is required to refer to outer's p
        nonlocal p
        if e[0] == 'add':
            p.append(e)
        elif e[0] == 'rem':
            p = [ x for x in p if not (x[1] == e[1]) ]
    for i in [["add","test1"],["add","test2"],["rem","test2"],["rem","test1"]]:
        touch(i)
outer()