oob*_*boo 293 python closures global python-nonlocal
Python nonlocal语句做了什么(在Python 3.0及更高版本中)?
官方Python网站上没有文档,help("nonlocal")也没有用.
Ano*_*non 415
比较这个,不使用nonlocal:
x = 0
def outer():
x = 1
def inner():
x = 2
print("inner:", x)
inner()
print("outer:", x)
outer()
print("global:", x)
# inner: 2
# outer: 1
# global: 0
Run Code Online (Sandbox Code Playgroud)
对此,使用nonlocal,其中inner()的x现在也是outer()的x:
x = 0
def outer():
x = 1
def inner():
nonlocal x
x = 2
print("inner:", x)
inner()
print("outer:", x)
outer()
print("global:", x)
# inner: 2
# outer: 2
# global: 0
Run Code Online (Sandbox Code Playgroud)
如果我们要使用
global它,它将绑定x到正确的"全局"值:Run Code Online (Sandbox Code Playgroud)x = 0 def outer(): x = 1 def inner(): global x x = 2 print("inner:", x) inner() print("outer:", x) outer() print("global:", x) # inner: 2 # outer: 1 # global: 2
Sin*_*ion 39
谷歌搜索"python nonlocal"出现了Proposal,PEP 3104,它完整地描述了该声明背后的语法和推理.简而言之,它的工作方式与global语句完全相同,不同之处在于它用于引用既不是全局也不是函数本地的变量.
以下是您可以使用此功能的简要示例.可以重写计数器生成器以使用它,使其看起来更像是带闭包的语言的习语.
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
Run Code Online (Sandbox Code Playgroud)
显然,你可以把它写成一个生成器,如:
def counter_generator():
count = 0
while True:
count += 1
yield count
Run Code Online (Sandbox Code Playgroud)
不过,虽然这是完全地道的蟒蛇,它似乎是第一个版本将是初学者更明显一点.通过调用返回的函数正确使用生成器是一个常见的混淆点.第一个版本显式返回一个函数.
小智 14
@ooboo:
它与源代码中的参考点"最接近".这被称为"词汇范围",现在是标准的> 40年.
Python的类成员实际上是在一个被称为字典的字典中,__dict__并且永远不会被词法范围所覆盖.
如果您没有指定nonlocal但是x = 7,它将创建一个新的局部变量"x".如果你指定nonlocal,它将找到"最接近的""x"并分配给它.如果您指定nonlocal并且没有"x",它将显示错误消息.
关键字global对我来说似乎总是很奇怪,因为除了最外面的关键字之外,它会高兴地忽略所有其他"x".奇怪的.
小智 14
帮助('nonlocal')
nonlocal声明
Run Code Online (Sandbox Code Playgroud)nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*该
nonlocal语句使列出的标识符引用最近的封闭范围中先前绑定的变量.这很重要,因为绑定的默认行为是首先搜索本地名称空间.除了全局(模块)范围之外,该语句还允许封装代码重新绑定局部范围之外的变量.
nonlocal与语句中列出的名称不同,语句中 列出的名称global必须引用封闭范围中的预先存在的绑定(无法明确确定应创建新绑定的范围).
nonlocal声明中列出的名称不得与本地作用域中的预先存在的绑定冲突.也可以看看:
PEP 3104 - 访问外部范围中
的名称nonlocal声明的规范.相关帮助主题:global,NAMESPACES
来源:Python语言参考
引用《Python 3参考》:
非本地语句使列出的标识符引用最近的包围范围中的先前绑定的变量(全局变量除外)。
如参考文献中所述,如果有多个嵌套函数,则仅修改最近的封闭函数中的变量:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
x = 2
innermost()
if x == 3: print('Inner x has been modified')
x = 1
inner()
if x == 3: print('Outer x has been modified')
x = 0
outer()
if x == 3: print('Global x has been modified')
# Inner x has been modified
Run Code Online (Sandbox Code Playgroud)
“最近”变量可以相隔几个级别:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
innermost()
x = 1
inner()
if x == 3: print('Outer x has been modified')
x = 0
outer()
if x == 3: print('Global x has been modified')
# Outer x has been modified
Run Code Online (Sandbox Code Playgroud)
但是它不能是全局变量:
def outer():
def inner():
def innermost():
nonlocal x
x = 3
innermost()
inner()
x = 0
outer()
if x == 3: print('Global x has been modified')
# SyntaxError: no binding for nonlocal 'x' found
Run Code Online (Sandbox Code Playgroud)