为什么在Python中修改父框架仅适用于模块框架?

时间:2014-05-06 15:36:24

标签: python python-2.7

我正在玩inspect.stack()。我尝试修改父框架的局部变量,它似乎仅在父框架是模块级别时才起作用。以下代码显示了这一点(Python 2.7):

import inspect


def outer():
    a = 10 
    print a
    modify()
    print a


def modify():
    inspect.stack()[1][0].f_locals['a'] = 8888

outer()

a = 20 
print a
modify()
print a

当父框架是一个函数时,为什么它不起作用?我可以让它发挥作用吗?

1 个答案:

答案 0 :(得分:6)

模块堆栈框架的f_localsglobals()! 您可以通过在is函数中打印globals()modify的比较来验证这一点:

def modify():
    print(inspect.stack()[1][0].f_locals is globals())
    inspect.stack()[1][0].f_locals['a'] = 8888

通过此更改,输出为:

$python3 modify.py 
10
False
10
20
True
8888

修改globals() 返回的词典有效(请参阅this问题)。 显式 documented模块使用简单的dict实现其命名空间:

  

模块由import语句导入(请参阅导入部分   声明)。 模块对象具有由a实现的命名空间   字典对象(这是由...引用的字典   模块中定义的函数的func_globals属性。

locals()返回的词典必须是本地命名空间:

  

注意不应修改此词典的内容;更改可能不会影响使用的本地和自由变量的值   翻译。

python2的某些版本中修改locals()时,在函数内部使用exec语句时可以正常工作。尝试在exec ''函数中添加outer,看看输出是否发生变化(它不会发生变化!但更有可能)。

编辑:在python 2.7.6上我可以使它工作如果堆栈帧使用exec语句没有对局部变量的赋值在代码中。例如,outer定义为:

def outer():
    exec('a = 10')
    print(a)
    modify()
    print(a)
    locals()['a'] = 9999
    print(a)

我得到了输出:

$python2 modify.py 
10
False
8888
9999
20
True
8888

但是,如果我在a = 10之后添加exec,请执行以下操作:

def outer():
    exec('a = 10')
    a = 10
    print(a)
    modify()
    print(a)
    locals()['a'] = 9999
    print(a)

结果是:

$python2 modify.py 
10
False
10
10
20
True
8888

我希望这能告诉你,分配给当地人工作的条件确实很少,绝对不可靠。

在python3中的AFAIK locals()返回的字典总是只是真实命名空间的副本,因此修改它永远不会有效。但是也不能保证。

f_locals属性返回的值只是locals()在此时返回的值。

总结:没有,有没有可靠的方法来修改通用堆栈帧的本地命名空间。您不能修改,删除或添加新的局部变量到通用堆栈框架的命名空间。