nonlocal在Python 3.x中做什么?


关闭调试问题,OP需要非局部的,并没有意识到它,请使用Is it possible To modify variable in python that Is outer, but not global, scope?代替。

虽然Python 2在2020年1月1日正式不支持,但如果出于某种原因,您被迫维护Python 2。并且需要与nonlocal等价的,请参见Python 2.x中的nonlocal关键字。


当前回答

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)

其他回答

简而言之,它允许您在外部(但非全局)作用域中为变量赋值。参阅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习惯用法,但对于初学者来说,第一个版本似乎更明显一些。通过调用返回的函数正确使用生成器是一个常见的混淆点。第一个版本显式返回一个函数。

使用“非局部”内部函数(即嵌套内部函数)可以获得外部父函数的特定变量的读和写权限。而nonlocal只能在内部函数中使用 例如:

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和编程并不熟悉)是,“非局部”是在迭代函数中使用全局功能的一种方式,而不是在代码本身中使用。一个函数之间的全局语句。

引用自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