提问人:FlashDD 提问时间:10/9/2022 更新时间:10/9/2022 访问量:35
奇怪的 python 闭包变量访问
Strange python closure variable access
问:
在尝试实现带有闭包的装饰器时,我遇到了一个有点奇怪的行为,其中可以读取变量,但如果稍后尝试赋值它,它甚至在赋值之前就变得未定义。
def run_once(fn):
to_run = True
def decorated(*args, **kwargs):
if to_run:
print(to_run) #this access works
#to_run = False #while this doesn't
return fn(*args, **kwargs)
return decorated
class A:
def __init__(self):
self.c=0
@run_once
def method1(self):
self.c+=1
print(f"Ran {self.c} times")
a=A()
a.method1()
a.method1()
a.method1()
上面的代码运行。
但如果未注释,则失败,并在赋值前引用 UnboundLocalError: local variable 'to_run'to_run = False
我发现我能阅读它真的很奇怪,但是如果我尝试在 if 的正文中分配它,它会在以前没有的地方失败。
我是否遗漏了一些明显的范围界定规则?
答:
4赞
rdas
10/9/2022
#1
由于您正在尝试从外部范围修改变量,因此您需要告诉 python 您正在尝试从外部范围访问该变量:
def run_once(fn):
to_run = True
def decorated(*args, **kwargs):
nonlocal to_run # use the variable from outer scope
if to_run:
print(to_run)
to_run = False # set the flag in the outer scope
return fn(*args, **kwargs)
return decorated
结果:
True
Ran 1 times
评论
1赞
Tom Karzes
10/9/2022
@FlashDD 在函数中,如果您不对变量进行任何赋值,它将自动在更高的范围内查找它。但是,如果您确实从函数中的任何位置分配给它,那么它将使其成为该函数的局部变量,除非您(从函数内部)显式将其声明为 或 。请注意,这是在 Python 3 中添加的。global
nonlocal
nonlocal
评论