python 中的 locals() 和对象引用

locals() and object reference in python

我对 python 如何跟踪 locals() 中的对象感到好奇。

考虑以下脚本:

import gc


class T(object):
    pass


def func1():

    t = T()

    #locals()
    del t
    #locals()

    for o in gc.get_objects():
        if type(o) is T:
            print("STILL EXISTS")


func1()

运行 两个 locals() 调用评论(如上)没有给我任何消息,表明创建的 T() 对象被垃圾收集。

当我使用第一个 locals() 命令 运行 它(删除第一个注释)时,它似乎创建了一个字典,其中包含对我的 t 对象的引用。该字典未与任何名称相关联,因此我不希望该字典在没有被垃圾收集的情况下继续存在。

问题是,运行宁代码,我得到 "STILL EXISTS"。即使我从函数命名空间中删除 t,该对象也不会被垃圾回收,因为 locals() 返回的字典仍在引用它。

有趣的是,如果我再次调用 locals()(删除上面代码中的第二条注释),那么字典会以某种方式更新,它不包含 t,对象是垃圾收集成功(我没有收到 "STILL EXISTS" 消息)。

我觉得这个行为有点奇怪。

问题是:

  1. locals()返回的字典很长正常吗 活过,甚至没有将它与任何名字联系起来?
  2. 从当前范围删除名称时,此词典不会自动更新是正常的还是有任何原因?

编辑:我正在使用 cpython 3.6

谢谢!

locals() 很奇怪。在函数内部,每个 locals() 调用都会将当前局部变量值复制到与堆栈帧关联的字典中,并 returns 字典中。 dict not 用于实际的局部变量查找,但它 附加到 frame 对象,并且它不是每次都是新的 dict;同一个堆栈帧中的所有 locals() 个调用重用同一个字典。

当您调用 locals() 时,locals dict 现在具有对当前由局部变量引用的所有对象的引用。这将使这些对象保持活动状态,直到堆栈帧死亡,或者在该堆栈帧内使用不同的局部变量值进行新的 locals() 调用。其他一些事情也会更新局部字典,例如检索堆栈帧对象的 f_locals 属性,但局部变量赋值不会自行更新局部字典。