代码之家  ›  专栏  ›  技术社区  ›  marius

如何强制更新不同堆栈框架的Python locals()字典?

  •  4
  • marius  · 技术社区  · 9 年前

    在Python2(不确定3)中,只有在实际调用locals()时,本地字典才会更新。因此,例如。

    l=locals()
    x=2
    l['x']
    

    失败,因为 l 里面没有钥匙“x”,但是

    l=locals()
    x=2
    locals()
    l['x']
    

    返回2。

    我正在寻找一种强制更新本地字典的方法,但诀窍是我处于不同的堆栈框架中。例如,我希望

    l=locals()
    x=2
    force_update()
    l['x']
    

    我需要写 force_update() 作用我知道,从所述函数中,我可以通过 inspect.currentframe().f_back ,甚至通过 inspect.currentframe().f_back.f_locals ,但如何强制更新?

    如果这看起来很复杂,我的主要目标是编写一个函数,它是 "{some} string".format(**dict(globals(),**locals())) 所以我不必每次都打出来,而是可以 fmt("{some} string") 这样做,我遇到了上面的问题。

    编辑 :下面是Martjin的答案,下面就是我想要的解决方案。人们可以精确地了解他们如何获得被调用方的堆栈帧,这里我通过 partial .

    from functools import partial
    from inspect import currentframe
    
    fmt = partial(lambda s,f: s.format(**dict(globals(),**f.f_locals)),f=currentframe())
    x=2
    print fmt("{x}") #prints "2"
    
    1 回复  |  直到 9 年前
        1
  •  2
  •   Martijn Pieters    9 年前

    仅仅 访问 f_locals 在帧对象上 触发复制,因此使用 inspect.currentframe().f_back.f_locals 足够了 .

    请参阅 frame_getlocals() function frameobject.c 实施:

    static PyObject *
    frame_getlocals(PyFrameObject *f, void *closure)
    {
        PyFrame_FastToLocals(f);
        Py_INCREF(f->f_locals);
        return f->f_locals;
    }
    

    PyFrame_FastToLocals 是用于将数据从内部数组跟踪局部值复制到字典的函数。 frame_getlocals 用于实现 frame.f_locals 描述符(属性);查看 frame_getsetlist definition .

    这个 PyFrame_FastToLocalsWithError 上面使用的函数是 确切地 什么 locals() 用于生成相同的词典(通过 wrapping 这个 PyEval_GetLocals function ).