Python 3中的"nonlocal"怎么用?

478 投票
10 回答
174368 浏览
提问于 2025-04-15 13:32

nonlocal 在 Python 3.x 中有什么用?


为了避免调试问题,特别是当提问者需要使用 nonlocal 但自己没有意识到时,请参考 是否可以修改在外部作用域但不是全局作用域中的变量?

虽然 Python 2 从 2020 年 1 月 1 日起 官方不再支持,但如果你因为某种原因需要维护 Python 2.x 的代码,并且需要一个类似于 nonlocal 的功能,可以查看 Python 2.x 中的 nonlocal 关键字

10 个回答

56

在谷歌搜索“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 中是非常标准的,但对于初学者来说,第一种写法可能会更容易理解。正确使用生成器,尤其是调用返回的函数,常常让人感到困惑。第一种写法明确地返回了一个函数。

129

简单来说,它让你可以在一个外部的(但不是全局的)范围内给变量赋值。想了解更多细节,可以查看 PEP 3104

657

对比一下,不使用 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 就会绑定到真正的“全局”值:

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

撰写回答