418

Pythonnonlocal语句有什么作用(在 Python 3.0 及更高版本中)?

Python 官方网站上没有文档,help("nonlocal")也无法正常工作。

4

9 回答 9

580

比较一下,不使用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, where inner()'sx现在也是outer()'s 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到正确的“全局”值:

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
于 2009-08-11T17:53:30.780 回答
108

简而言之,它允许您将值分配给外部(但非全局)范围内的变量。有关所有血腥细节,请参阅PEP 3104

于 2009-08-11T17:40:52.477 回答
47

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

于 2009-08-11T17:50:45.793 回答
22

@ooboo:

它将“最接近”源代码中的参考点。这被称为“词汇范围”,并且已经成为标准超过 40 年了。

Python 的类成员实际上在一个名为的字典中__dict__,并且永远不会通过词法作用域来访问。

如果你不指定nonlocal但做x = 7,它将创建一个新的局部变量“x”。如果您指定nonlocal,它将找到“最接近的”“x”并分配给它。如果您指定nonlocal并且没有“x”,它将给您一条错误消息。

这个关键字global对我来说一直很奇怪,因为它会很高兴地忽略除最外面的“x”之外的所有其他“x”。奇怪的。

于 2010-12-05T13:30:02.083 回答
15

help('nonlocal')nonlocal语句


    nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*

nonlocal语句使列出的标识符引用最近的封闭范围内的先前绑定的变量。这很重要,因为绑定的默认行为是首先搜索本地命名空间。该语句允许封装代码重新绑定全局(模块)范围之外的局部范围之外的变量。

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

语句中列出的名称nonlocal不得与本地范围内的预先存在的绑定发生冲突。

也可以看看:

PEP 3104 - 访问外部范围内的名称声明
的规范nonlocal

相关帮助主题:全局、命名空间

来源:Python 语言参考

于 2011-08-04T11:01:39.580 回答
10

引用Python 3 参考

nonlocal 语句导致列出的标识符引用最近的封闭范围内的先前绑定的变量,不包括全局变量。

如参考资料中所述,在多个嵌套函数的情况下,仅修改最近的封闭函数中的变量:

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
于 2018-03-21T11:27:06.800 回答
3

我个人对“非本地”语句的理解(请原谅,因为我是 Python 和一般编程的新手)是“非本地”是一种在迭代函数中使用全局功能而不是代码本身的方法. 如果您愿意,可以在函数之间使用全局语句。

于 2011-08-04T10:25:00.040 回答
3
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)
于 2015-05-06T13:11:20.783 回答
0

使用“非本地”内部函数(即嵌套内部函数)可以获得外部父函数的特定变量的读取和“写入”权限。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)
于 2018-03-21T07:28:52.410 回答