如果符号出现,Python函数的闭包似乎有问题 引用已分配:
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
如果我只是为了测试替换:
- p = [ x for x in p if not (x[1] == e[1]logig is) ]
+ a = [ x for x in p if not (x[1] == e[1]) ]
错误消失了,但是代码不是我想要的。 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
,您应该使用 nonlocal 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 = ...
)。
参见nonlocal
in the Python reference documentation ,scopes 的引用文档,和PEP 3104其中提出了nonlocal
语法。 nonlocal
仅存在于 Python 3 中,但是 there is a workaround如果有必要使用Python 2。
关于python 闭包/嵌套函数在分配给外部数组时失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52411459/