page contents

Python 的闭包是如何实现的?nonlocal 关键字的作用是什么?

学 Python 的时候,很多人第一次遇到“闭包”这个词,都觉得挺玄乎的,好像是某种很高级的技巧。其实闭包本质上不复杂,它就是一个函数把外层作用域里的变量“记住”了。用起来挺顺手,但理解原理和 nonlocal 的作用,能让你少踩不少坑。

attachments-2025-10-QCOTxGgo68e9b5e533c18.png学 Python 的时候,很多人第一次遇到“闭包”这个词,都觉得挺玄乎的,好像是某种很高级的技巧。其实闭包本质上不复杂,它就是一个函数把外层作用域里的变量“记住”了。用起来挺顺手,但理解原理和 nonlocal 的作用,能让你少踩不少坑。

闭包是怎么回事

先随便写个例子:

def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

c1 = make_counter()
print(c1())  # 1
print(c1())  # 2

这里 counter 这个函数就是闭包,它记住了 make_counter 里的 count 变量。哪怕 make_counter 已经返回结束,counter 还能继续用这个 count

为什么?因为 Python 在函数定义的时候,不光存了函数的代码,还把用到的外层变量打包在 __closure__ 里保存下来。你要是不信,可以直接看:

print(c1.__closure__)
print([cell.cell_contents for cell in c1.__closure__])

输出里你能看到,count 就活在那里面。这个就是闭包的底层实现方式。

如果不用 nonlocal 会怎样

上面那段代码里用了 nonlocal count,如果你去掉,会报错:

def make_counter():
    count = 0
    def counter():
        count += 1  # UnboundLocalError
        return count
    return counter

报错的原因是,Python 解释器在编译 counter 的时候发现你写了 count += 1,它会觉得你要在 counter 里面定义一个新的局部变量 count。结果原来的 count 就被遮蔽了,但这个新变量又没初始化,所以直接炸了。

nonlocal 的作用就是告诉解释器:别给我创建新的局部变量,我就是要用外层函数作用域里的那个变量。

这在写闭包的时候特别常见。比如计数器、缓存函数、装饰器这些地方,很多逻辑都是通过 nonlocal 把外层状态保存住。

再举个装饰器的例子:

def call_times(func):
    count = 0
    def wrapper(*args, **kwargs):
        nonlocal count
        count += 1
        print(f"{func.__name__} called {count} times")
        return func(*args, **kwargs)
    return wrapper

@call_times
def greet(name):
    print("Hello,", name)

greet("Tom")
greet("Jerry")

运行结果大概是:

greet called 1 times
Hello, Tom
greet called 2 times
Hello, Jerry

这就是 nonlocal 在闭包里最常用的场景。

如果外层变量再往外一层,比如全局变量,那就不用 nonlocal,而是 global。区别在于:

  • global 改的是模块级变量
  • nonlocal 改的是外层函数里的变量

记住这点就够用了。

总结一下:闭包就是函数加上它周围的环境变量打包在一起,形成了一个“带记忆的函数”。而 nonlocal 是闭包里操作外层局部变量时必不可少的关键字,不然就会遇到作用域的坑。

你要是经常写装饰器或者一些带状态的函数,闭包 + nonlocal 绝对是老朋友。

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

1407 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 2224 文章
  3. Pack 1407 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章