为什么在Python中修改父框架仅适用于模块框架?
问题内容:
我在玩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
当父框架是函数时,为什么它不起作用?我可以使它工作吗?
问题答案:
该f_locals
模块堆栈帧的是它globals()
!您可以通过在函数内部打印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()
确实
有效(请参阅此问题)。它 明确地
记载该模块实现了自己的一个简单的命名空间dict
:
模块通过该
import
语句导入(请参见import语句一节)。
模块对象具有由字典对象(这是由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返回的字典locals()
是 永远 只是一个真正的命名空间的副本,因此修改它永远不会奏效。但是,也不保证。
该f_locals
属性返回的值locals()
就是该点返回的值。
总结: 没有 , 没有 可靠的方法来修改通用堆栈框架的本地名称空间。您不能修改,删除或向通用堆栈框架的名称空间添加新的局部变量。