python - Python 是否会垃圾收集在函数范围内不再引用的变量?
问题描述
在等待一个长时间运行的函数完成执行时,我开始思考垃圾收集器是否会清理对不再使用的变量的引用。
比如说,我有一个类似的功能:
def long_running_function():
x = MemoryIntensiveObject()
print id(x)
# lots of hard work done here which does not reference x
return
我很好奇解释器是否足够聪明,能够意识到 x 不再被使用并且可以被取消引用。这有点难以测试,因为我可以编写代码来检查它的引用计数,但是这会隐含地引用它,这消除了这样做的原因。
我的想法是,也许当函数被解析并生成字节码时,它可能会以这样一种方式生成,当它不再被引用时,它会允许它清理对象。
或者,答案是否更简单,只要我们仍在“可以”使用它的范围内,它就不会被清理?
解决方案
不,只要在当前范围内仍然定义了引用该对象的名称,CPython 就不会对对象进行垃圾收集。
这是因为,即使x
代码中没有将名称作为文字引用,调用vars()
或locals()
仍然可以获取本地命名空间字典的副本(在最后一次引用之前或之后x
),因此整个本地命名空间有效“根”它引用的值,直到执行离开其范围。
我不确定其他实现如何做到这一点。特别是,在像 PyPy、Jython 或 IronPython 这样的 JIT 编译实现中,至少在理论上可以执行这种优化。JVM 和 CLR JIT 实际上确实在其他语言上执行了这种优化。这些平台上的 Python 是否能够利用这一优势完全取决于 Python 代码编译成的字节码。
推荐阅读
- winapi - 如何获取未记录的 DShellFolderViewEvents 的方法签名
- java - 尝试光栅化 SVG 文件时出现 Batik 1.14 错误
- javascript - 当标记 onClick 触发状态更新时,黑色方块出现在第一个标记周围
- r - 按扇区计算 R 中的标准差
- vue.js - 使用 Vue.JS 在 Video.JS 中显示视频字幕
- spring-boot - 基于客户端的数据转换设计模式
- java - 图像未在 Java Swing 中添加为背景
- c++ - 使用 std::thread 并加入并行性
- css - 如何使用 Flex 更改列顺序和保持在同一行的长文本
- google-chrome-extension - 网络未显示在 Manifest v3 的 Chrome 扩展背景页面中