是否可以将sys.\u getframe()从解释器中运行的python代码中返回的python frame对象写入?

2024-06-07 00:36:04 发布

您现在位置:Python中文网/ 问答频道 /正文

关于This question,解释器中有一点脚手架来检查框架对象,sys._getframe()可以检索到这些框架对象。frame对象似乎是只读的,但是我在文档中找不到任何明确说明这一点的东西。有人能确认这些对象是可写的(以某种方式)还是只读的吗?在

import sys

def foobar():
    xx='foo'
    ff = sys._getframe()
    ff.f_locals['xx'] = 'bar'
    print xx

if __name__ == '__main__':
    foobar()

这将在运行时输出“foo”,但下面的文章演示了从交互式shell中的当前框架运行时变量是可写的。在


Tags: 对象文档框架foosys方式thisframe
2条回答

从CPython源,Objects/frameobject.c

static PyMemberDef frame_memberlist[] = {
    {"f_back",      T_OBJECT,       OFF(f_back),    RO},
    {"f_code",      T_OBJECT,       OFF(f_code),    RO},
    {"f_builtins",  T_OBJECT,       OFF(f_builtins),RO},
    {"f_globals",   T_OBJECT,       OFF(f_globals), RO},
    {"f_lasti",     T_INT,          OFF(f_lasti),   RO},
    {"f_exc_type",  T_OBJECT,       OFF(f_exc_type)},
    {"f_exc_value", T_OBJECT,       OFF(f_exc_value)},
    {"f_exc_traceback", T_OBJECT,   OFF(f_exc_traceback)},
    {NULL}    /* Sentinel */
};
...
static PyGetSetDef frame_getsetlist[] = {
    {"f_locals",    (getter)frame_getlocals, NULL, NULL},
    {"f_lineno",    (getter)frame_getlineno,
                    (setter)frame_setlineno, NULL},
    {"f_trace",     (getter)frame_gettrace, (setter)frame_settrace, NULL},
    {"f_restricted",(getter)frame_getrestricted,NULL, NULL},
    {0}
};

对于PyMemberDef,标志RO或{}表示它的属性是只读的。对于PyGetSetDef,如果它只有一个getter,那么它是只读的。这意味着除了f_exc_typef_exc_valuef_exc_traceback和{}之外的所有属性在创建后都是只读的。在文档中,Data model下也提到了这一点。在

属性引用的对象不一定是只读的。你可以这样做:

^{pr2}$

虽然这在解释器中有效,但在函数内部失败。执行引擎为局部变量(f_fastlocals)使用一个单独的数组,在访问时它被合并到f_locals,但相反的情况并非如此。在

>>> def foo():
...   x = 3
...   f = sys._getframe()
...   print f.f_locals['x']
...   x = 4
...   print f.f_locals['x']
...   d = f.f_locals
...   x = 5
...   print d['x']
...   f.f_locals
...   print d['x']
...
>>> foo()
3
4
4
5
>>>

在全局框架中,f_local引用f_globals,这使得这个技巧在解释器中起作用。修改f_globals可以工作,但会影响整个模块。在

NXC的f_locals['foo']示例可以工作,因为代码在模块范围内。在这种情况下,f_locals是f_globals,并且f_globals是可修改的,修改反映在模块中。在

在函数作用域内,locals()和f\u locals是可写的,但是“[更改可能不会影响解释器使用的局部变量的值]。”1这是一个实现选择。在CPython中,有一个针对局部变量的优化字节码,LOAD峎FAST。在Python中,定义函数后(几乎总是)知道局部变量,CPython使用索引查找来获取变量值,而不是字典查找。在

理论上,字典查找可以代理该表,但这是一项大量的工作,收效甚微。在

“local variables are known”(本地变量已知)的例外情况是,如果函数使用exec语句,则不推荐使用“from module import*”的情况。对于这些情况,生成的字节码是不同的,而且速度较慢。在

相关问题 更多 >