在Python 3.3.1中,这有效:
i = 76
def A():
global i
i += 10
print(i) # 76
A()
print(i) # 86
这也有效:
def enclosing_function():
i = 76
def A():
nonlocal i
i += 10
print(i) # 76
A()
print(i) # 86
enclosing_function()
但这不起作用:
i = 76
def A():
nonlocal i # "SyntaxError: no binding for nonlocal 'i' found"
i += 10
print(i)
A()
print(i)
nonlocal
关键字states的文档(重点已添加):
非本地语句会导致列出的标识符引用 先前绑定的变量位于最近的封闭范围中。
在第三个例子中,“最近的封闭范围”恰好是全局范围。那为什么不起作用?
我注意到文档继续说明(强调添加):
[
nonlocal
]语句允许封装代码 除了全局之外,重新绑定本地范围之外的变量 (模块)范围。
但是,严格地说,这并不意味着我在第三个例子中所做的事情不应该起作用。
答案 0 :(得分:6)
名称的搜索顺序是LEGB,即Local,Enclosing,Global,Builtin。因此,全球范围不是一个封闭的范围。
修改强>
来自docs:
非本地语句会导致列出的标识符引用 先前在最近的封闭范围内绑定变量。这是 很重要,因为绑定的默认行为是搜索 本地名称空间首先该语句允许封装代码 除了全局之外,重新定义局部范围之外的变量 (模块)范围。
答案 1 :(得分:3)
答案是全球范围并没有包含任何内容 - 它对所有事物都是全球性的。在这种情况下使用global
关键字。
答案 2 :(得分:1)
为什么模块的范围被认为是全局的而不是封闭的?它仍然不是其他模块的全局(好吧,除非你做
from module import *
),是吗?
如果你在module
的命名空间中添加了一些名字;它在任何使用module
的模块中都可见,即它对整个Python进程都是全局的。
通常,您的应用程序应使用尽可能少的可变全局变量。见Why globals are bad?:
因此,nonlocal
允许偶然创建全局变量会很糟糕。如果要修改全局变量;您可以直接使用global
关键字。
global
是最具破坏性的:可能影响程序中任何位置的模块的所有用途nonlocal
破坏性较小:受外部()函数范围的限制(在编译时检查绑定)您可以在PEP: 3104
Access to Names in Outer Scopes中了解nonlocal
背后的历史和动机。
答案 3 :(得分:0)
这取决于边界案例:
nonlocals带有一些我们需要注意的敏感区域。首先,与全局语句不同,当评估非本地语时,非本地名称实际上必须先在封闭的def范围内分配,否则您将收到错误 - 您无法通过重新分配它们来动态创建它们在封闭范围内。实际上,在调用嵌套函数或嵌套函数
之前,它们会在函数定义时检查>>>def tester(start):
def nested(label):
nonlocal state #nonlocals must already exist in enclosing def!
state = 0
print(label, state)
return nested
SyntaxError: no binding for nonlocal 'state' found
>>>def tester(start):
def nested(label):
global state #Globals dont have to exits yet when declared
state = 0 #This creates the name in the module now
print(label, state)
return nested
>>> F = tester(0)
>>> F('abc')
abc 0
>>> state
0
其次,非本地将范围查找限制为仅包含defs; nonlocals不会在封闭模块的全局范围内查找,也不会在所有def中查找内置范围,即使它们已经存在:
例如: -
>>>spam = 99
>>>def tester():
def nested():
nonlocal spam #Must be in a def, not the module!
print('current=', spam)
spam += 1
return nested
SyntaxError: no binding for nonlocal 'spam' found
一旦你意识到python通常不知道创建一个全新名称的封闭范围,这些限制是有意义的。在之前的列表中,垃圾邮件应该在测试人员<中分配/ strong>,还是外面的模块?因为这是不明确的,Python必须在函数创建时解决非局部,而不是函数调用时间。