提问人:ooboo 提问时间:8/12/2009 最后编辑:Super Kai - Kazuya Itoooboo 更新时间:2/3/2023 访问量:167253
“非本地”在 Python 3 中有什么作用?
What does "nonlocal" do in Python 3?
问:
Python 3.x 中有什么作用?nonlocal
要关闭 OP 需要非本地
且未实现的调试问题,请使用 是否可以在 python 中修改外部但非全局范围内的变量?
尽管自 2020 年 1 月 1 日起正式不支持 Python 2,但如果由于某种原因您被迫维护 Python 2.x 代码库并需要与 nonlocal 等效的代码库,请参阅 Python 2.x 中的 nonlocal 关键字。
答:
简而言之,它允许您为外部(但非全局)范围内的变量赋值。请参阅 PEP 3104 了解所有血腥细节。
在谷歌上搜索“python nonlocal”,发现了提案PEP 3104,它完全描述了该声明背后的语法和推理。简而言之,它的工作方式与语句完全相同,只是它用于引用既不是函数的全局变量也不是局部变量。global
下面是一个简短的示例,说明您可以用它做什么。可以重写计数器生成器以使用它,使其看起来更像是带有闭包的语言的习语。
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
显然,你可以把它写成一个生成器,比如:
def counter_generator():
count = 0
while True:
count += 1
yield count
但是,虽然这是完全惯用的 python,但对于初学者来说,第一个版本似乎会更明显一些。通过调用返回的函数来正确使用生成器是一个常见的混淆点。第一个版本显式返回一个函数。
评论
itertools.count()
nonlocal
比较一下,不使用: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
为此,使用非本地
的,其中 's 现在也是 's: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
如果我们使用 global,它将绑定到正确的“global
”值:x
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
评论
它采用“最接近”源代码中引用点的那个。 这被称为“词汇范围界定”,现在是 >40 年的标准。
Python 的类成员实际上位于一个名为的字典中,并且永远不会通过词法范围到达。__dict__
如果你不指定但做,它将创建一个新的局部变量 “x”。
如果您指定了 ,它将找到“最接近的”“x”并分配给它。
如果指定并且没有“x”,它将为您提供错误消息。nonlocal
x = 7
nonlocal
nonlocal
这个关键字对我来说总是很奇怪,因为它会很乐意忽略除了最外面的那个之外的所有其他“x”。global
评论
print(x)
nonlocal
global
我个人对“非局部”语句的理解(请原谅我,因为我是 Python 和编程的新手)是“非局部”是一种在迭代函数中使用全局功能的方式,而不是代码本身的主体。函数之间的全局语句(如果愿意的话)。
help('非本地') 声明
nonlocal
nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*
该语句使列出的标识符引用 最近封闭范围内以前绑定的变量。这是 重要,因为绑定的默认行为是搜索 本地命名空间优先。该语句允许封装的代码 除全局范围外,重新绑定局部范围之外的变量 (模块)作用域。
nonlocal
与语句中列出的名称不同,语句中列出的名称必须引用 封闭范围(应在其中创建新绑定的范围) 无法明确确定)。
nonlocal
global
声明中列出的名称不得与前 本地作用域中的现有绑定。
nonlocal
另请参阅:
PEP 3104 - 访问外部作用域
中的名称 语句的规范。nonlocal
相关帮助主题:全局、命名空间
来源:Python 语言参考
评论
help()
help()
a = 0 #1. global variable with respect to every function in program
def f():
a = 0 #2. nonlocal with respect to function g
def g():
nonlocal a
a=a+1
print("The value of 'a' using nonlocal is ", a)
def h():
global a #3. using global variable
a=a+5
print("The value of a using global is ", a)
def i():
a = 0 #4. variable separated from all others
print("The value of 'a' inside a function is ", a)
g()
h()
i()
print("The value of 'a' global before any function", a)
f()
print("The value of 'a' global after using function f ", a)
具有“非局部”内部函数(即;嵌套内部函数)可以获取外部父函数的特定变量的读和“写”权限。非局部只能在内部函数中使用 例如:
a = 10
def Outer(msg):
a = 20
b = 30
def Inner():
c = 50
d = 60
print("MU LCL =",locals())
nonlocal a
a = 100
ans = a+c
print("Hello from Inner",ans)
print("value of a Inner : ",a)
Inner()
print("value of a Outer : ",a)
res = Outer("Hello World")
print(res)
print("value of a Global : ",a)
引用 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
“最近”变量可以相距几级:
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
但它不能是全局变量:
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
文档如下:
非本地语句使列出的标识符引用 最接近的封闭范围内的先前绑定变量,不包括 全局变量。...
例如,in 可以访问非局部变量 foo = 10 in,但不能访问非局部变量 foo = 5 in 或全局变量
foo =
0 outside,如下所示:nonlocal foo
inner()
middle()
outer()
outer()
foo = 0 # <- ✖
def outer():
foo = 5 # <- ✖
def middle():
foo = 10 # <- 〇
def inner():
nonlocal foo # Here
foo += 1
print(foo) # 11
inner()
middle()
outer()
评论
"There is no documentation for nonlocal".
实际上,您可以为 Python 3 及更高版本的文档做help(keyword_in_string)