Python非本地语句/关键字

nonlocal在Python 3.x中做什么?


关闭调试问题,其中OP需要nonlocal,并没有意识到它,请使用是否可以在python中修改变量,在外部,但不是全局范围?< / >。

虽然Python 2是在2020年1月1日正式不支持,如果由于某种原因你被迫维护Python 2。如果需要nonlocal的等效值,请参见Python 2.x中的nonlocal关键字。

154304 次浏览

简而言之,它允许您在外部(但非全局)作用域中为变量赋值。参见PEP 3104获取所有血腥的细节。

谷歌搜索“python nonlocal”会出现Proposal, 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,但似乎第一个版本对初学者来说更明显一些。通过调用返回的函数正确使用生成器是一个常见的混淆点。第一个版本显式返回一个函数。

比较,不使用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

为此,使用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

如果我们要使用global,它会将x绑定到正确的“global”;值:

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__的字典中,并且永远不会通过词法作用域到达。

如果你没有指定nonlocal而是指定x = 7,它将创建一个新的局部变量"x"。 如果你确实指定了nonlocal,它会找到&;“x"然后赋值给它。 如果你指定了nonlocal并且没有"x",它会给你一个错误信息

关键字global对我来说一直很奇怪,因为它会很高兴地忽略所有其他的“;x"除了最外层。

我个人对“非局部”语句的理解(请原谅我对Python和编程并不熟悉)是,“非局部”是在迭代函数中使用全局功能的一种方式,而不是在代码本身中使用。一个函数之间的全局语句。

< p >帮助(外地的) nonlocal语句


    nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*
nonlocal语句使列出的标识符指向 先前在最近的封闭范围内绑定的变量。这是 重要的原因是绑定的默认行为是搜索 首先是本地名称空间。语句允许封装的代码 重新绑定局部作用域之外的变量 (模块)范围。< / p >

nonlocal语句中列出的名称,不同于nonlocal语句中列出的名称 global语句,必须引用对象中预先存在的绑定 封闭范围(应在其中创建新绑定的范围 不能明确确定)。

nonlocal语句中列出的名称不能与pre- .冲突

.本地范围内的现有绑定

参见:

PEP 3104 -外部作用域中名称的访问
nonlocal语句的规范

相关帮助主题:全局、NAMESPACES

来源:Python语言参考

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)

与'非局部'内部函数(即嵌套内部函数)可以读取&` < em > < / em >写 `权限对于外部父函数的特定变量。而nonlocal只能在内部函数中使用 如:< / p >

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