注意:这个问题假设 Python 2.7.3。
我正在寻找一种理智的方法来动态修改函数的本地命名空间,最好是以一种给主体函数添加最少混乱的方式。
我的想法看起来像这样:
import os
from namespace_updater import update_locals
def somefunc(x, y, z):
# ...
# ...
# this and that
# ...
# ...
if os.environ.get('FROBNICATE'):
from frobnitz import frobnicate
update_locals(frobnicate(locals()))
#
# life goes on, possibly with duly frobnicated local variables...
# ...
# ...
# ...
谢谢!
PS:以下是不起作用的方法。
最天真的方法是这样的:
locals().update(new_locals(locals())
...但是文档locals()
非常明确地警告不要依赖这种巫术来修改局部变量,所以请不要将其作为答案提交(除非您可以为无视文档的警告提供一个很好的案例)。
天真的规模中的下一个是
for k, v in new_locals(locals()).items():
exec ('%s = v' % k)
AFAICT,这样的代码不能“碍事”(即,它必须在函数体中),这并不理想。但真正的交易破坏者是exec ('%s = v' % k)
黑客可能会导致一些奇怪的错误。
当我写“怪异的错误”时,我的意思是“对于exec ('%s = v' % k)
像我一样脆弱的人来说看起来很奇怪的错误”。我对这个黑客的掌握有多脆弱?要回答这个问题,请考虑下面的脚本。它具有三种变体:(1)完全如图所示;(2) 删除第18行的前导#
后;(3) 在删除第#
15 行和第 18 行中的第一个之后(即对于这个变体,没有代码被注释掉)。我无法预测此脚本的变体 (2) 和 (3) 的行为。我什至无法以超过 50% 的置信度预测变体 (1) 的行为。这就是我对exec ('%s = v' % k)
黑客。除非您可以自信且正确地预测该脚本的三个变体的行为方式(在 python 2.7 下),否则可以肯定地说,您对情况的掌握与我的一样脆弱,您可能也应该远离exec ('%s = v' % k)
。
x = 'global x' # 01
y = 'global y' # 02
def main(): # 03
x = 'local x' # 04
y = 'local y' # 05
run(locals()) # 06
print 'OK' # 07
return 0 # 08
# 09
def run(namespace): # 10
global y # 11
print locals().keys() # 12
for k, v in namespace.items(): # 13
print '%s <- %r' % (k, v) # 14
exec ('%s = v' % k) #in locals() # 15
print locals().keys() # 16
x = x # 17
#z = lambda: k # 18
print x # 19
print y # 20
# 21
exit(main()) # 22