如何访问Python函数内的变量?函数变量存储在内存什么位置?
函数内部变量的存储位置
以下内容基于CPython解释器实现说明:
函数内部的局部变量既不存储在globals()对应的全局命名空间,也不存储在函数对象的__dict__属性中:
- 函数处于运行状态时,CPython会为其创建独立的栈帧(frame object),局部变量默认存储在栈帧的快速访问数组中,只有调用栈帧的
f_locals属性时,才会将局部变量同步到字典结构中供访问。 - 函数执行结束后,对应的栈帧会被自动销毁,栈帧持有的局部变量引用会被释放:如果对应对象没有其他引用,就会被垃圾回收机制回收,原内存地址会被重新分配。
globals()存储的是模块级全局命名空间,仅保存模块顶层定义的对象;函数的__dict__是函数对象自身的属性字典,仅用来存储手动绑定到函数对象上的自定义属性,二者和函数运行时的内部局部变量完全无关,自然找不到目标变量。
你测试时两次调用reveal()打印出me的id完全相同,本质是Python的字符串驻留机制导致的:"where"属于短字符串,会被CPython全局缓存驻留,两次创建都会指向同一个内存地址,和函数局部变量是否持久存储没有关系。
函数内变量的访问规则
遵循Python标准作用域规则时,函数外部无法直接访问函数运行时的局部变量,核心原因就是函数执行结束后栈帧销毁,局部变量的引用就不存在了。
如果确实需要访问,仅在特定场景下可以通过以下方式实现,注意这些方式不属于常规业务开发的推荐写法:
- 持有函数运行时的栈帧对象:可以通过
sys._getframe()在函数内部获取当前栈帧并返回,外部可以通过栈帧的f_locals字典访问对应局部变量,只要栈帧对象被持有,对应局部变量就不会被垃圾回收,示例代码:
import sys def reveal(): me = "where" # 返回当前函数的栈帧对象 return sys._getframe() frame = reveal() print(frame.f_locals["me"]) # 输出 where
- 闭包场景下访问自由变量:如果局部变量被嵌套函数引用形成闭包,变量会被包装为cell对象存储在嵌套函数的
__closure__属性中,可以通过cell_contents属性访问,示例代码:
def outer(): me = "where" def inner(): return me return inner inner_func = outer() # __closure__是元组,按顺序对应闭包引用的自由变量 print(inner_func.__closure__[0].cell_contents) # 输出 where
测试代码的风险提示
你用ctypes.c_long.from_address(memory_address)直接读内存地址的操作非常危险:
- 这种写法完全绕过了Python的内存管理机制,属于未定义行为:如果对应内存已经被GC回收并分配给其他对象,读到的是完全无意义的脏数据,如果尝试写入值,会直接导致Python解释器崩溃。
- 你读出来的值为1,本质是因为CPython对象内存布局的第一个字段是引用计数
ob_refcnt,你读取的是对象的引用计数值,不是变量本身的内容。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

