4

在 Python 2(不确定 3)中,locals 字典仅在您实际调用 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"
4

1 回答 1

2

简单地访问f_locals一个框架对象就会触发复制,所以使用inspect.currentframe().f_back.f_locals 就足够了

查看实现中的frame_getlocals()函数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定义

上面使用的PyFrame_FastToLocalsWithError函数正是locals()用于生成相同字典的函数(通过包装函数PyEval_GetLocals

于 2016-04-17T15:10:02.413 回答