You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python:外部函数返回后nonlocal变量的内存存储位置问询

闭包中nonlocal变量的存储位置解析

示例代码

def g():
    in_g=100
    def f1():
        nonlocal in_g
        in_g = 10
    def f2():
        nonlocal in_g
        print(in_g)
    return (f1,f2)
(f1, f2) = g()
f2() #prints 100
f1()
f2() #prints 10

问题描述

内部函数f1和f2均通过闭包访问变量in_g。当外部函数g返回后,nonlocal变量in_g在内存中存储于何处?
我假设在g执行期间,in_g位于g调用对应的栈帧中,因此g、f1、f2访问in_g时指向同一栈内存地址。但如示例所示,g返回后f1和f2仍能访问同一内存地址的in_g,而此时g的栈帧已不存在。


解答

你的猜测其实只对了一半——在g执行时,in_g确实一开始在栈帧里,但当Python检测到内部函数要捕获这个变量(也就是用nonlocal声明,或者直接引用它)时,这个变量会被移到堆内存中的一个闭包对象(closure cell)里,而不是留在栈上。

具体来说:

  • 当g被调用时,Python会创建一个栈帧,但发现f1和f2都引用了in_g并且用了nonlocal,就会把in_g打包成一个cell对象,存到堆里。
  • 这个cell对象会被f1和f2的__closure__属性引用着,所以即使g的栈帧销毁了,f1和f2依然能通过这个引用找到in_g的内存位置。
  • 你可以自己验证一下,执行以下代码:
    print(f1.__closure__)  # 会输出包含cell对象的元组
    print(f1.__closure__[0].cell_contents)  # 直接获取in_g的当前值
    

简单总结:闭包捕获的变量不会留在栈帧里,而是被放到堆上的cell对象中,由内部函数的闭包引用持有,所以外部函数返回后,这些变量依然能被访问和修改。


内容的提问来源于stack exchange,提问作者user42768

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:28:14