python中的locals()和对象引用

Sup*_*Geo 4 python garbage-collection cpython

我发现了一些关于 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()
Run Code Online (Sandbox Code Playgroud)

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

当我使用第一个locals()命令运行它(删除第一个注释)时,它似乎创建了一个包含对我的t对象的引用的字典。这本词典与任何名字都没有关联,所以我不希望这个 dict 能像没有被垃圾收集一样存在。

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

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

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

问题是:

  1. 返回的字典locals()即使没有与任何名称相关联也很长寿命是否正常?
  2. 从当前范围中删除名称时,此字典不会自动更新是正常的还是有任何原因?

编辑:我正在使用 cpython 3.6

谢谢!

use*_*ica 5

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

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