我正在尝试理解Python 3变量范围和nonlocal
。
考虑以下功能(这只是一个例子):
def build_property(something):
def deco(func):
def getter(self):
return getattr(self, something)
def setter(self, value):
setattr(self, something, value)
return property(getter, setter)
return deco
没有nonlocal
,这样可以正常工作。但是,如果现在我想根据something
有条件地创建getter和setter,我需要非本地。
def build_property(something):
def deco(func):
nonlocal something # This is needed
if something.startswith('A'):
getter = None
else:
def getter(self):
return getattr(self, something)
if something.startswith('B'):
setter = None
else:
def setter(self, value):
setattr(self, something, value)
return property(getter, setter)
return deco
为什么在一个案例中需要nonlocal
,而在另一个案例中不需要something
?换句话说,为什么nonlocal
如果在第一种情况下正确找到(没有nonlocal
),但在第二种情况下我得到:“UnboundLocalError:局部变量'某些'在赋值之前被引用”如果{{1}不存在?
答案 0 :(得分:2)
首先: nonlocal
在您编写的代码中不是必需的。您没有更改something
指向的对象。
第二:在某些情况下,您需要使用nonlocal
。以下是一些需要nonlocal
的代码。请注意,所有断言都是正确的(即,它们不会引发AssertionError)。
def main():
variable = 1
def function():
variable = 2
function()
assert variable == 1
def function():
nonlocal variable
variable = 2
function()
assert variable == 2
if __name__ == '__main__':
main()
第三:您提供的代码不会产生您声称的错误。如果我删除nonlocal
行,并调用以下函数,则不会出现错误。
build_property('A')(lambda: True)
build_property('B')(lambda: True)
build_property('C')(lambda: True)
答案 1 :(得分:-1)
def A(d):
outer = object()
d["outer"] = outer
def B():
print locals()
assert d["outer"] is outer #This fails and never reaches
inner = object()
d=dict() #this line.
print locals()
def C():
print locals()
assert d["outer"] is outer #This goes on fine.
inner = object()
print locals()
return B,C
=> b,c = A(dict())
=> c()
-snip, AOK-
=> b()
UnboundLocalError: local variable 'd' referenced before assignment
对不起,我值得拥有火焰。上面的代码我写得很快,使得之前的答案是一堆废话。
但令人惊讶的是。我一直认为python(2.x)是一种完全没有前瞻性的语言,在最后一刻评估所有内容......
对不起现在的话题感到抱歉。