函数局部变量未被GC清理,两次调用id相同的原因及解决方法
两次调用函数f()时变量a的id相同的原因及相关问题解答
原因:CPython的字符串驻留优化
你遇到的现象确实是CPython的**字符串驻留(String Interning)**优化导致的:
- 代码中
"wat wat wat wat wat wat wat wat"是编译阶段就能确定的字符串字面量,CPython会在编译时将这类字符串存入全局的字符串常量池,后续每次用到该字面量时,都会直接复用池中的同一个对象,而非重新创建新对象。 - 函数
f()每次调用时,变量a只是引用了常量池里的已有对象,因此两次输出的id完全一致。 - 垃圾回收器不会回收这个对象,因为它被常量池的全局引用持有,属于可达对象,所以
gc.collect()和等待时间都无法改变这个结果。
能否强制清理该对象?
很难通过常规手段强制清理:
- 字符串常量池的引用由CPython内部维护,Python没有提供公开API来手动移除其中的对象。
- 若想避免对象复用,可以将字符串改为动态生成(而非直接使用字面量),比如把
a = "wat wat wat wat wat wat wat wat"改成a = "wat " * 8,这样每次调用函数时都会生成新的字符串对象,两次输出的id就会不同。
测试代码
import time def f(): a = "wat wat wat wat wat wat wat wat" print(id(a)) f() for i in range(30): time.sleep(1) s = "/" if i % 2 == 0 else "\\" print(s, end="", flush=True) print() f() # Tested with python 3.10.8 # 140443262854256 # ///////////////\ # 140443262854256
内容的提问来源于stack exchange,提问作者Alpensin
相关产品推荐
相关产品推荐

